1 /*
2  * Copyright (c) 2016 Wind River Systems, Inc.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @file
9  *
10  * Object type abstraction.
11  *
12  * Each object type that can be used as a "fork" provides:
13  *
14  * - a definition for fork_t (a reference to a fork) and fork_obj_t (an
15  *   instance of the fork object)
16  * - a 'fork_init' function that initializes the object
17  * - a 'take' function that simulates taking the fork (eg. k_sem_take)
18  * - a 'drop' function that simulates dropping the fork (eg. k_mutex_unlock)
19  * - a 'fork_type_str' string defining the object type
20  *
21  * When using dynamic objects, the instances of the fork objects are placed
22  * automatically in the fork_objs[] array . References to these are in turn
23  * placed automatically in the forks[] array, the array of references to the
24  * forks.
25  *
26  * When using static objects, references to each object must be put by hand in
27  * the forks[] array.
28  */
29 
30 #ifndef phil_obj_abstract__h
31 #define phil_obj_abstract__h
32 
33 #define MAGIC 0xa5a5ee11
34 
35 #if (FORKS == FIFOS) || (FORKS == LIFOS)
36 	struct packet {
37 		void *next;
38 		int data;
39 	} orig_packet[NUM_PHIL];
40 #endif
41 
42 #if FORKS == SEMAPHORES
43 	#define fork_t struct k_sem *
44 	#if STATIC_OBJS
45 		K_SEM_DEFINE(fork0, 1, 1);
46 		K_SEM_DEFINE(fork1, 1, 1);
47 		K_SEM_DEFINE(fork2, 1, 1);
48 		K_SEM_DEFINE(fork3, 1, 1);
49 		K_SEM_DEFINE(fork4, 1, 1);
50 		K_SEM_DEFINE(fork5, 1, 1);
51 	#else
52 		#define fork_obj_t struct k_sem
53 		#define fork_init(x) k_sem_init(x, 1, 1)
54 	#endif
55 	#define take(x) k_sem_take(x, K_FOREVER)
56 	#define drop(x) k_sem_give(x)
57 	#define fork_type_str "semaphores"
58 #elif FORKS == MUTEXES
59 	#define fork_t struct k_mutex *
60 	#if STATIC_OBJS
61 		K_MUTEX_DEFINE(fork0);
62 		K_MUTEX_DEFINE(fork1);
63 		K_MUTEX_DEFINE(fork2);
64 		K_MUTEX_DEFINE(fork3);
65 		K_MUTEX_DEFINE(fork4);
66 		K_MUTEX_DEFINE(fork5);
67 	#else
68 		#define fork_obj_t struct k_mutex
69 		#define fork_init(x) k_mutex_init(x)
70 	#endif
71 	#define take(x) k_mutex_lock(x, K_FOREVER)
72 	#define drop(x) k_mutex_unlock(x)
73 	#define fork_type_str "mutexes"
74 #elif FORKS == STACKS
75 	#define fork_t struct k_stack *
76 	#if STATIC_OBJS
77 		#error "not implemented yet."
78 	#else
79 		typedef struct {
80 			struct k_stack stack;
81 			uint32_t stack_mem[1];
82 		} fork_obj_t;
83 		#define fork_init(x) do { \
84 			k_stack_init(x, (stack_data_t *)((x) + 1), 1); \
85 			k_stack_push(x, MAGIC); \
86 		} while ((0))
87 	#endif
88 	#define take(x) do { \
89 		stack_data_t data; k_stack_pop(x, &data, K_FOREVER); \
90 		__ASSERT(data == MAGIC, "data was %lx\n", data); \
91 	} while ((0))
92 	#define drop(x) k_stack_push(x, MAGIC)
93 	#define fork_type_str "stacks"
94 #elif FORKS == FIFOS
95 	#define fork_t struct k_fifo *
96 	#if STATIC_OBJS
97 		#error "not implemented yet."
98 	#else
99 		typedef struct {
100 			struct k_fifo fifo;
101 			struct packet data;
102 		} fork_obj_t;
103 		#define fork_init(x) do { \
104 			k_fifo_init(x); \
105 			((fork_obj_t *)(x))->data.data = MAGIC; \
106 			k_fifo_put(x, &(((fork_obj_t *)(x))->data)); \
107 		} while ((0))
108 	#endif
109 	#define take(x) do { \
110 		struct packet *data; \
111 		data = k_fifo_get(x, K_FOREVER); \
112 		__ASSERT(data->data == MAGIC, ""); \
113 	} while ((0))
114 	#define drop(x) k_fifo_put(x, &(((fork_obj_t *)(x))->data))
115 	#define fork_type_str "fifos"
116 #elif FORKS == LIFOS
117 	#define fork_t struct k_lifo *
118 	#if STATIC_OBJS
119 		#error "not implemented yet."
120 	#else
121 		typedef struct {
122 			struct k_lifo lifo;
123 			struct packet data;
124 		} fork_obj_t;
125 		#define fork_init(x) do { \
126 			k_lifo_init(x); \
127 			((fork_obj_t *)(x))->data.data = MAGIC; \
128 			k_lifo_put(x, &(((fork_obj_t *)(x))->data)); \
129 		} while ((0))
130 	#endif
131 	#define take(x) do { \
132 		struct packet *data; \
133 		data = k_lifo_get(x, K_FOREVER); \
134 		__ASSERT(data->data == MAGIC, ""); \
135 	} while ((0))
136 	#define drop(x) k_lifo_put(x, &(((fork_obj_t *)(x))->data))
137 	#define fork_type_str "lifos"
138 #else
139 	#error unknown fork type
140 #endif
141 
142 #if STATIC_OBJS
143 	#define obj_init_type "static"
144 #else
145 	#define obj_init_type "dynamic"
146 	fork_obj_t fork_objs[NUM_PHIL];
147 #endif
148 
149 static fork_t forks[NUM_PHIL] = {
150 #if STATIC_OBJS
151 	&fork0, &fork1, &fork2,
152 	&fork3, &fork4, &fork5,
153 #else
154 	(fork_t)&fork_objs[0], (fork_t)&fork_objs[1], (fork_t)&fork_objs[2],
155 	(fork_t)&fork_objs[3], (fork_t)&fork_objs[4], (fork_t)&fork_objs[5],
156 #endif
157 };
158 
159 static K_THREAD_STACK_ARRAY_DEFINE(stacks, NUM_PHIL, STACK_SIZE);
160 static struct k_thread threads[NUM_PHIL];
161 
162 #endif /* phil_obj_abstract__h */
163