3 * @author Dario Faggioli <faggioli@gandalf.sssup.it>
5 * @brief FRSH core thread related functions not implamented in managers..
11 #include <fres_contract.h>
12 #include <fres_contract_idl.h>
13 #include <frsh_core.h>
14 #include <frsh_error.h>
15 #include <fres_blocks.h>
18 #include <fra_generic.h>
20 #include "frsh_forb.h"
23 #include <aqcpu_res.h>
26 #include <cpucg_res.h>
29 #include <diskbfq_res.h>
33 * frsh_thread_bind(), bind a thread to a vres
35 * possible return values:
37 * FRSH_ERR_NOT_INITIALIZED
38 * FRSH_BAD_ARGUMENT(*) (invalid or dummy vres)
39 * FRSH_ERR_NOT_CONTRACTED_VRES(*)
40 * FRSH_ERR_ALREADY_BOUND(*)
41 * FRSH_ERR_INTERNAL_ERROR(*) (something wrong with AQuoSA or with the service thread internal data structures)
44 (const frsh_vres_id_t vres,
45 const frsh_thread_id_t thread)
48 ret = fra_insert_thread_vres(&thread, vres->allocator->res_type, vres);
51 if (vres->allocator->bind_thread) {
52 ret = vres->allocator->bind_thread(vres, thread);
54 ret = FRSH_ERR_NOT_IMPLEMENTED;
56 if (ret) goto err_delete;
61 fra_delete_thread_vres(&thread, vres->allocator->res_type);
63 return FRSH_ERR_INTERNAL_ERROR;
67 * frsh_thread_unbind(), unbind a thread from a vres
70 * Notice that, since we don't know from which VRES the
71 * thread should be unbound, we unboind it from all the
72 * ones it is attached to!
74 * possible return values:
76 * FRSH_ERR_NOT_INITIALIZED
77 * FRSH_BAD_ARGUMENT(*) (invalid thread)
78 * FRSH_ERR_NOT_BOUND(*)
79 * FRSH_ERR_INTERNAL_ERROR(*) (something wrong with AQuoSA or with the service thread internal data structures)
81 int frsh_thread_unbind(const frsh_thread_id_t thread)
86 /* Unbound from FRSH_RT_PROCESSOR resource (if any) */
87 vres = fra_get_vres_thread_vres(&thread, FRSH_RT_PROCESSOR);
89 if (vres->allocator->unbind_thread) {
90 ret = vres->allocator->unbind_thread(thread);
92 ret = FRSH_ERR_NOT_IMPLEMENTED;
96 ret = fra_delete_thread_vres(&thread, vres->allocator->res_type);
100 /* Unbound from FRSH_RT_DISK resource (if any) */
101 vres = fra_get_vres_thread_vres(&thread, FRSH_RT_DISK);
103 if (vres->allocator->unbind_thread) {
104 ret = vres->allocator->unbind_thread(thread);
106 ret = FRSH_ERR_NOT_IMPLEMENTED;
110 ret = fra_delete_thread_vres(&thread, vres->allocator->res_type);
114 return FRSH_NO_ERROR;
116 return FRSH_ERR_INTERNAL_ERROR;
120 * structure used to pass the new created thread (or better its wrapper) the
121 * arguments it needs to bind itself to the vres.
123 typedef struct wrapper_pthread_arg {
124 frsh_thread_id_t parent_thread_id;
125 frsh_thread_id_t *thread_id;
126 frsh_thread_code_t pthread_code; /**< function to be running in thread */
127 void *pthread_arg; /**< thread arguments*/
129 sem_t *stopper; /**< semaphore to synchronize frsh call and wrapper thread */
131 } wrapper_pthread_arg_t;
135 * pthread_t pthread_id;
138 * } FOSA_THREAD_ID_T_OPAQUE;
144 * possible exit status:
145 * FRSH_ERR_INTENRAL_ERROR (something wrong with threads and signal handling)
146 * FRSH_ERR_TOO_MANY_TASKS(*)
147 * FRSH_ERR_BAD_ARGUMENT(*) (invalid vres)
148 * FRSH_ERR_NOT_CONTRACTED_VRES(*)
149 * whatever the user provided code 'pthread_code' returns
151 static void* wrapper_pthread(void *arg)
153 wrapper_pthread_arg_t* pth = (wrapper_pthread_arg_t*) arg;
154 frsh_thread_id_t* thread_id = pth->thread_id;
155 void *thread_arg = pth->pthread_arg;
156 frsh_thread_code_t thread_code = pth->pthread_code;
158 /* bind this thread to vres */
159 *thread_id = fosa_thread_self();
160 pth->errcode = frsh_thread_bind(pth->vres, *thread_id);
162 sem_post(pth->stopper);
163 /* No access to pth is allowed after this point, it can vanish already */
165 if (pth->errcode) return NULL;
167 /* execute thread code */
168 return thread_code(thread_arg);
172 * API call for 'frsh_thread_create_and_bind()', as said prepares the
173 * wrapper code argument data structure, create the new thread and wait
174 * its acknowledgment before stepping over
176 * possible return values:
178 * FRSH_ERR_NOT_INITIALIZED
179 * FRSH_ERR_BAD_ARGUMENT (NULL thread or thread_code)
180 * whatever 'fosa_thread_create()' returns
181 * FRSH_ERR_INTERNAL_ERROR
183 int frsh_thread_create_and_bind
184 (const frsh_vres_id_t vres,
185 frsh_thread_id_t *thread,
186 frsh_thread_attr_t *attr,
187 frsh_thread_code_t thread_code,
190 wrapper_pthread_arg_t wp_arg;
194 sem_init(&stopper, 0, 0);
196 if (!thread || !thread_code || !attr)
197 return FRSH_ERR_BAD_ARGUMENT;
199 wp_arg.parent_thread_id = fosa_thread_self();
200 wp_arg.thread_id = thread;
201 wp_arg.pthread_code = thread_code;
202 wp_arg.pthread_arg = arg;
204 wp_arg.stopper = &stopper;
206 /* create the wrapper thread */
207 pthread_attr_setinheritsched(attr, PTHREAD_EXPLICIT_SCHED);
208 pthread_attr_setscope(attr, PTHREAD_SCOPE_SYSTEM);
209 ret = fosa_thread_create(thread, attr, wrapper_pthread,
217 return (wp_arg.errcode);
220 int frsh_thread_create_in_background
221 (frsh_thread_code_t thread_code,
222 const void *thread_arg,
223 const frsh_contract_label_t contract_label,
224 frsh_thread_attr_t *attr,
225 frsh_thread_id_t *thread,
226 frsh_vres_id_t *vres_id)
228 frsh_contract_t contract;
229 fosa_rel_time_t zero_msec = fosa_msec_to_rel_time(0);
232 /* Background contract creation and negotiation */
233 frsh_contract_init(&contract);
234 frsh_contract_set_resource_and_label(&contract,
238 frsh_contract_set_basic_params(&contract,
241 FRSH_WT_INDETERMINATE,
244 /* It will be accepted: we are asking for 0 budget over 0 period */
245 ret = frsh_contract_negotiate(&contract, vres_id);
246 if (ret !=0) goto error;
248 ret = fosa_thread_create(thread, attr, thread_code, (void*) thread_arg);
249 if (ret != 0) goto error;
251 ret = fra_insert_thread_vres(thread, FRSH_RT_PROCESSOR, *vres_id);
259 int frsh_thread_get_vres_id
260 (const frsh_thread_id_t thread,
261 frsh_vres_id_t *vres_id)
264 return FRSH_ERR_BAD_ARGUMENT;
268 * Why PROCESSOR and not DISK or NETWORK (or whatever) ??
270 *vres_id = fra_get_vres_thread_vres(&thread,
273 return vres_id ? 0 : EINVAL;
276 int frsh_service_thread_set_data
277 (const struct timespec *budget,
278 const struct timespec *period,
281 return FRSH_ERR_NOT_IMPLEMENTED;
284 int frsh_service_thread_get_data
285 (frsh_rel_time_t *budget,
286 frsh_rel_time_t *period)
288 return FRSH_ERR_NOT_IMPLEMENTED;