Boot Linux faster!

Check our new training course

Boot Linux faster!

Check our new training course
and Creative Commons CC-BY-SA
lecture and lab materials

Bootlin logo

Elixir Cross Referencer

/*
 * Copyright (c) 2016 Wind River Systems, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @file
 *
 * Object type abstraction.
 *
 * Each object type that can be used as a "fork" provides:
 *
 * - a definition for fork_t (a reference to a fork) and fork_obj_t (an
 *   instance of the fork object)
 * - a 'fork_init' function that initializes the object
 * - a 'take' function that simulates taking the fork (eg. k_sem_take)
 * - a 'drop' function that simulates dropping the fork (eg. k_mutex_unlock)
 * - a 'fork_type_str' string defining the object type
 *
 * When using dynamic objects, the instances of the fork objects are placed
 * automatically in the fork_objs[] array . References to these are in turn
 * placed automatically in the forks[] array, the array of references to the
 * forks.
 *
 * When using static objects, references to each object must be put by hand in
 * the forks[] array.
 */

#ifndef phil_obj_abstract__h
#define phil_obj_abstract__h

#define MAGIC 0xa5a5ee11

#if (FORKS == FIFOS) || (FORKS == LIFOS)
	struct packet {
		void *next;
		int data;
	} orig_packet[NUM_PHIL];
#endif

#if FORKS == SEMAPHORES
	#define fork_t struct k_sem *
	#if STATIC_OBJS
		K_SEM_DEFINE(fork0, 1, 1);
		K_SEM_DEFINE(fork1, 1, 1);
		K_SEM_DEFINE(fork2, 1, 1);
		K_SEM_DEFINE(fork3, 1, 1);
		K_SEM_DEFINE(fork4, 1, 1);
		K_SEM_DEFINE(fork5, 1, 1);
	#else
		#define fork_obj_t struct k_sem
		#define fork_init(x) k_sem_init(x, 1, 1)
	#endif
	#define take(x) k_sem_take(x, K_FOREVER)
	#define drop(x) k_sem_give(x)
	#define fork_type_str "semaphores"
#elif FORKS == MUTEXES
	#define fork_t struct k_mutex *
	#if STATIC_OBJS
		K_MUTEX_DEFINE(fork0);
		K_MUTEX_DEFINE(fork1);
		K_MUTEX_DEFINE(fork2);
		K_MUTEX_DEFINE(fork3);
		K_MUTEX_DEFINE(fork4);
		K_MUTEX_DEFINE(fork5);
	#else
		#define fork_obj_t struct k_mutex
		#define fork_init(x) k_mutex_init(x)
	#endif
	#define take(x) k_mutex_lock(x, K_FOREVER)
	#define drop(x) k_mutex_unlock(x)
	#define fork_type_str "mutexes"
#elif FORKS == STACKS
	#define fork_t struct k_stack *
	#if STATIC_OBJS
		#error "not implemented yet."
	#else
		typedef struct {
			struct k_stack stack;
			u32_t stack_mem[1];
		} fork_obj_t;
		#define fork_init(x) do { \
			k_stack_init(x, (u32_t *)((x) + 1), 1); \
			k_stack_push(x, MAGIC); \
		} while ((0))
	#endif
	#define take(x) do { \
		u32_t data; k_stack_pop(x, &data, K_FOREVER); \
		__ASSERT(data == MAGIC, "data was %x\n", data); \
	} while ((0))
	#define drop(x) k_stack_push(x, MAGIC)
	#define fork_type_str "stacks"
#elif FORKS == FIFOS
	#define fork_t struct k_fifo *
	#if STATIC_OBJS
		#error "not implemented yet."
	#else
		typedef struct {
			struct k_fifo fifo;
			struct packet data;
		} fork_obj_t;
		#define fork_init(x) do { \
			k_fifo_init(x); \
			((fork_obj_t *)(x))->data.data = MAGIC; \
			k_fifo_put(x, &(((fork_obj_t *)(x))->data)); \
		} while ((0))
	#endif
	#define take(x) do { \
		struct packet *data; \
		data = k_fifo_get(x, K_FOREVER); \
		__ASSERT(data->data == MAGIC, ""); \
	} while ((0))
	#define drop(x) k_fifo_put(x, &(((fork_obj_t *)(x))->data))
	#define fork_type_str "fifos"
#elif FORKS == LIFOS
	#define fork_t struct k_lifo *
	#if STATIC_OBJS
		#error "not implemented yet."
	#else
		typedef struct {
			struct k_lifo lifo;
			struct packet data;
		} fork_obj_t;
		#define fork_init(x) do { \
			k_lifo_init(x); \
			((fork_obj_t *)(x))->data.data = MAGIC; \
			k_lifo_put(x, &(((fork_obj_t *)(x))->data)); \
		} while ((0))
	#endif
	#define take(x) do { \
		struct packet *data; \
		data = k_lifo_get(x, K_FOREVER); \
		__ASSERT(data->data == MAGIC, ""); \
	} while ((0))
	#define drop(x) k_lifo_put(x, &(((fork_obj_t *)(x))->data))
	#define fork_type_str "lifos"
#else
	#error unknown fork type
#endif

#if STATIC_OBJS
	#define obj_init_type "static"
#else
	#define obj_init_type "dynamic"
	fork_obj_t __kernel fork_objs[NUM_PHIL];
#endif

static fork_t forks[NUM_PHIL] = {
#if STATIC_OBJS
	&fork0, &fork1, &fork2,
	&fork3, &fork4, &fork5,
#else
	(fork_t)&fork_objs[0], (fork_t)&fork_objs[1], (fork_t)&fork_objs[2],
	(fork_t)&fork_objs[3], (fork_t)&fork_objs[4], (fork_t)&fork_objs[5],
#endif
};

static K_THREAD_STACK_ARRAY_DEFINE(stacks, NUM_PHIL, STACK_SIZE);
static struct k_thread __kernel threads[NUM_PHIL];

#endif /* phil_obj_abstract__h */