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)
47 struct fres_contract *contract = vres->perceived;
48 fres_block_resource *r = fres_contract_get_resource(contract);
51 ret = fra_insert_thread_vres(&thread, r->resource_type, vres);
53 switch(r->resource_type)
55 case FRSH_RT_PROCESSOR:
57 ret = fra_CPU_bind_thread(vres, thread);
62 ret = fra_DISK_bind_thread(vres, thread);
68 if (ret) goto err_delete;
73 fra_delete_thread_vres(&thread, r->resource_type);
75 return FRSH_ERR_INTERNAL_ERROR;
79 * frsh_thread_unbind(), unbind a thread from a vres
82 * Notice that, since we don't know from which VRES the
83 * thread should be unbound, we unboind it from all the
84 * ones it is attached to!
86 * possible return values:
88 * FRSH_ERR_NOT_INITIALIZED
89 * FRSH_BAD_ARGUMENT(*) (invalid thread)
90 * FRSH_ERR_NOT_BOUND(*)
91 * FRSH_ERR_INTERNAL_ERROR(*) (something wrong with AQuoSA or with the service thread internal data structures)
93 int frsh_thread_unbind(const frsh_thread_id_t thread)
96 struct fres_contract *contract;
97 fres_block_resource *r;
100 /* Unbound from FRSH_RT_PROCESSOR resource (if any) */
101 vres = fra_get_vres_thread_vres(&thread, FRSH_RT_PROCESSOR);
103 contract = vres->perceived;
104 r = fres_contract_get_resource(contract);
105 ret = fra_CPU_unbind_thread(thread);
108 ret = fra_delete_thread_vres(&thread, FRSH_RT_PROCESSOR);
112 /* Unbound from FRSH_RT_DISK resource (if any) */
113 vres = fra_get_vres_thread_vres(&thread, FRSH_RT_DISK);
115 contract = vres->perceived;
116 r = fres_contract_get_resource(contract);
117 ret = fra_DISK_unbind_thread(thread);
120 ret = fra_delete_thread_vres(&thread, FRSH_RT_DISK);
124 return FRSH_NO_ERROR;
126 return FRSH_ERR_INTERNAL_ERROR;
130 * structure used to pass the new created thread (or better its wrapper) the
131 * arguments it needs to bind itself to the vres.
133 typedef struct wrapper_pthread_arg {
134 frsh_thread_id_t parent_thread_id;
135 frsh_thread_id_t *thread_id;
136 frsh_thread_code_t pthread_code; /**< function to be running in thread */
137 void *pthread_arg; /**< thread arguments*/
139 sem_t *stopper; /**< semaphore to synchronize frsh call and wrapper thread */
141 } wrapper_pthread_arg_t;
145 * pthread_t pthread_id;
148 * } FOSA_THREAD_ID_T_OPAQUE;
154 * possible exit status:
155 * FRSH_ERR_INTENRAL_ERROR (something wrong with threads and signal handling)
156 * FRSH_ERR_TOO_MANY_TASKS(*)
157 * FRSH_ERR_BAD_ARGUMENT(*) (invalid vres)
158 * FRSH_ERR_NOT_CONTRACTED_VRES(*)
159 * whatever the user provided code 'pthread_code' returns
161 static void* wrapper_pthread(void *arg)
163 wrapper_pthread_arg_t* pth = (wrapper_pthread_arg_t*) arg;
164 frsh_thread_id_t* thread_id = pth->thread_id;
165 void *thread_arg = pth->pthread_arg;
166 frsh_thread_code_t thread_code = pth->pthread_code;
168 /* bind this thread to vres */
169 *thread_id = fosa_thread_self();
170 pth->errcode = frsh_thread_bind(pth->vres, *thread_id);
172 sem_post(pth->stopper);
173 /* No access to pth is allowed after this point, it can vanish already */
175 if (pth->errcode) return NULL;
177 /* execute thread code */
178 return thread_code(thread_arg);
182 * API call for 'frsh_thread_create_and_bind()', as said prepares the
183 * wrapper code argument data structure, create the new thread and wait
184 * its acknowledgment before stepping over
186 * possible return values:
188 * FRSH_ERR_NOT_INITIALIZED
189 * FRSH_ERR_BAD_ARGUMENT (NULL thread or thread_code)
190 * whatever 'fosa_thread_create()' returns
191 * FRSH_ERR_INTERNAL_ERROR
193 int frsh_thread_create_and_bind
194 (const frsh_vres_id_t vres,
195 frsh_thread_id_t *thread,
196 frsh_thread_attr_t *attr,
197 frsh_thread_code_t thread_code,
200 wrapper_pthread_arg_t wp_arg;
204 sem_init(&stopper, 0, 0);
206 if (!thread || !thread_code || !attr)
207 return FRSH_ERR_BAD_ARGUMENT;
209 wp_arg.parent_thread_id = fosa_thread_self();
210 wp_arg.thread_id = thread;
211 wp_arg.pthread_code = thread_code;
212 wp_arg.pthread_arg = arg;
214 wp_arg.stopper = &stopper;
216 /* create the wrapper thread */
217 pthread_attr_setinheritsched(attr, PTHREAD_EXPLICIT_SCHED);
218 pthread_attr_setscope(attr, PTHREAD_SCOPE_SYSTEM);
219 ret = fosa_thread_create(thread, attr, wrapper_pthread,
227 return (wp_arg.errcode);
230 int frsh_thread_create_in_background
231 (frsh_thread_code_t thread_code,
232 const void *thread_arg,
233 const frsh_contract_label_t contract_label,
234 frsh_thread_attr_t *attr,
235 frsh_thread_id_t *thread,
236 frsh_vres_id_t *vres_id)
238 frsh_contract_t contract;
239 fosa_rel_time_t zero_msec = fosa_msec_to_rel_time(0);
242 /* Background contract creation and negotiation */
243 frsh_contract_init(&contract);
244 frsh_contract_set_resource_and_label(&contract,
248 frsh_contract_set_basic_params(&contract,
251 FRSH_WT_INDETERMINATE,
254 /* It will be accepted: we are asking for 0 budget over 0 period */
255 ret = frsh_contract_negotiate(&contract, vres_id);
256 if (ret !=0) goto error;
258 ret = fosa_thread_create(thread, attr, thread_code, (void*) thread_arg);
259 if (ret != 0) goto error;
261 ret = fra_insert_thread_vres(thread, FRSH_RT_PROCESSOR, *vres_id);
269 int frsh_thread_get_vres_id
270 (const frsh_thread_id_t thread,
271 frsh_vres_id_t *vres_id)
274 return FRSH_ERR_BAD_ARGUMENT;
278 * Why PROCESSOR and not DISK or NETWORK (or whatever) ??
280 *vres_id = fra_get_vres_thread_vres(&thread,
283 return vres_id ? 0 : EINVAL;
286 int frsh_service_thread_set_data
287 (const struct timespec *budget,
288 const struct timespec *period,
291 return FRSH_ERR_NOT_IMPLEMENTED;
294 int frsh_service_thread_get_data
295 (frsh_rel_time_t *budget,
296 frsh_rel_time_t *period)
298 return FRSH_ERR_NOT_IMPLEMENTED;