-/* forward declaration of the wrapper function */
-static void *wrapper_pthread_create(void *warg);
-
-/*
- * API call for 'frsh_thread_create_and_bind()', as said prepares the
- * wrapper code argument data structure, create the new thread and wait
- * its acknowledgment before stepping over
- *
- * possible return values:
- * FRSH_NO_ERROR
- * FRSH_ERR_NOT_INITIALIZED
- * FRSH_ERR_BAD_ARGUMENT (NULL thread or thread_code)
- * whatever 'fosa_thread_create()' returns
- * FRSH_ERR_INTERNAL_ERROR (something wrong in signal handling)
- */
-int frsh_thread_create_and_bind(const frsh_vres_id_t vres,
- frsh_thread_id_t *thread,
- frsh_thread_attr_t *attr,
- frsh_thread_code_t thread_code,
- void *arg)
-{
- wrapper_pthread_arg_t wp;
- int thread_status;
- //sigset_t thread_wait_mask;
- frsh_signal_t wait_signal;
- frsh_signal_info_t wait_signal_info;
- struct timespec wait_signal_timeout;
-
- /* check for framework initialization and arguments */
- if (!frsh_initialized)
- PERROR_AND_RETURN(FRSH_ERR_NOT_INITIALIZED,
- "can't proceed before initializing FRSH with 'frsh_init()'!");
- if ((thread == NULL) || (thread_code == NULL))
- PERROR_AND_RETURN(FRSH_ERR_BAD_ARGUMENT,
- "can't create a thread with NULL thread_core or return it in a NULL thread");
- /*
- * setup the wrapper code and args for the new
- * created thread to fill in
- *
- * Remember:
- * frsh_thread_id_t => struct {
- * pthread_t pthread_id;
- * pid_t linux_pid;
- * tid_t linux_tid;
- * };
- */
- wp.parent_thread_id = fosa_thread_self();
- wp.thread_id = thread; /* directly fill the user provided thread descriptor pointer */
- //wp.pthread_pthread_id = &(thread->pthread_id);
- //wp.pthread_linux_pid = &(thread->linux_pid);
- //wp.pthread_linux_tid = &(thread->linux_tid);
- wp.vres = vres;
- wp.pthread_code = thread_code;
- wp.pthread_arg = arg;
- /* create the wrapper thread */
- thread_status = fosa_thread_create(NULL, attr, wrapper_pthread_create,(void*) &wp);
- if (thread_status != 0)
- PERROR_AND_RETURN(thread_status,
- "can't create the new thread");
- /* prepare a suited signal mask and wait for the new
- * thread to acknowledge us it has filled the pointers with the descriptor*/
- //pthread_sigmask(0, NULL, &thread_wait_mask);
- //sigdelset(&thread_wait_mask, FRSH_SCHEDULER_SIGNAL);
- wait_signal = FRSH_SCHEDULER_SIGNAL;
- fosa_set_accepted_signals(&wait_signal, 1);
- wait_signal_timeout.tv_sec = 0;
- wait_signal_timeout.tv_nsec = 500000000; /* half a second timeout!! */
- //if (sigsuspend(&thread_wait_mask) != -1)
- if (fosa_signal_timedwait(&wait_signal, 1, NULL, &wait_signal_info, &wait_signal_timeout) < 0)
- PERROR_AND_RETURN(FRSH_ERR_INTERNAL_ERROR,
- "can't synchronize with the new created thread");
- if (wait_signal_info.sival_int != FRSH_NO_ERROR)
- PERROR_AND_RETURN(wait_signal_info.sival_int,
- "can't create and bind the new thread");
- /* restore the signal mask to its original */
- //sigaddset(&thread_wait_mask, FRSH_SCHEDULER_SIGNAL);
- //pthread_sigmask(FRSH_SCHEDULER_SIGNAL, &thread_wait_mask, NULL);
-
- return FRSH_NO_ERROR;
-}
-
-/*
- * API call for 'frsh_thread_create_in_background()', as said creates a
- * background contract and negotiate it (we know they're always accepted
- * but we need to get the service thread account fo the new vres), then
- * create the new thread, exactly as seen in 'frsh_thread_create_and_bind()'
- * and wait for its acknowledgment
- *
- * possible return values:
- * FRSH_NO_ERROR
- * FRSH_ERR_NOT_INITIALIZED
- * FRSH_ERR_BAD_ARGUMENT (NULL thread_id, thread_code, contract_label or vres_id)
- * FRSH_ERR_TOO_MANY_VRES(*)
- * FRSH_ERR_CONTRACT_ID_ALREADY_EXISTS(*)
- * FRSH_ERR_CONTRACT_REJECTED(*)
- * whatever 'fosa_thread_create()' returns
- * FRSH_ERR_INTERNAL_ERROR(*) (something wrong with AQuoSA or with the service thread internal data structures)
- * FRSH_ERR_INTERNAL_ERROR (something wrong in signal handling)
- */
-int frsh_thread_create_in_background(frsh_thread_code_t thread_code,
- const void *thread_arg,
- const frsh_contract_label_t contract_label,
- frsh_thread_attr_t *attr,
- frsh_thread_id_t *thread_id,
- frsh_vres_id_t *vres_id)
-{
- frsh_contract_t contract;
- frsh_in_msg_t contract_msg;
- frsh_out_msg_t vres_msg;
-
- wrapper_pthread_arg_t wp;
- int thread_status;
- //sigset_t thread_wait_mask;
- frsh_signal_t wait_signal;
- frsh_signal_info_t wait_signal_info;
- frsh_rel_time_t wait_signal_timeout;
-
- /* check for framework initialization and arguments */
- if (!frsh_initialized)
- PERROR_AND_RETURN(FRSH_ERR_NOT_INITIALIZED,
- "can't proceed before initializing FRSH with 'frsh_init()'!");
- if ((thread_code == NULL) || (thread_id == NULL))
- PERROR_AND_RETURN(FRSH_ERR_BAD_ARGUMENT,
- "can't create a thread with NULL thread_code or return it in a NULL thread_id");
- if (contract_label == NULL)
- PERROR_AND_RETURN(FRSH_ERR_BAD_ARGUMENT,
- "can't give the contract a NULL contract_label");
- if (vres_id == NULL)
- PERROR_AND_RETURN(FRSH_ERR_BAD_ARGUMENT,
- "can't negotiate for a NULL vres_id");
-
- /* initialize a contract core parameters
- * exactly as if we've called 'frsh_contract_init()' */
- /* Core contract attributes setup */
- contract.resource_id = FRSH_RESOURCE_ID_DEFAULT;
- contract.resource_type = FRSH_RT_PROCESSOR;
- /* contract.contract_label not modified/initialized */
- contract.budget_min = FOSA_USEC_TO_REL_TIME(0);
- contract.period_max = FOSA_USEC_TO_REL_TIME(0);
- contract.workload = FRSH_WT_INDETERMINATE;
- contract.contract_type = FRSH_CT_REGULAR;
- contract.d_equals_t = true;
- contract.deadline = FOSA_USEC_TO_REL_TIME(0);
- contract.budget_overrun_signal = FRSH_NULL_SIGNAL;
- contract.budget_overrun_siginfo.sival_int = 0;
- contract.deadline_miss_signal = FRSH_NULL_SIGNAL;
- contract.deadline_miss_siginfo.sival_int = 0;
- /* setup id parameters of the contract
- * as if we've called 'frsh_contract_set_resource_and_label()' */
- contract.resource_type = FRSH_RT_PROCESSOR;
- contract.resource_id = FRSH_RESOURCE_ID_DEFAULT;
- strncpy(contract.contract_label, contract_label, FRSH_CONTRACT_LABEL_MAXLENGTH);
- /* setup basic contract parameters
- * (in order to specify it's a background contract!)
- * as if we've called 'frsh_contract_set_basic_params()' */
- contract.workload = FRSH_WT_INDETERMINATE;
- contract.contract_type = FRSH_CT_BACKGROUND;
- /* setup additional timing parameters for the contract
- * as if we've called 'frsh_contract_set_timing_reqs()' */
- contract.d_equals_t = true;
- /* ask the service thread for the contract negotiation
- * (as if we've called 'frsh_contract_negotiate()') */
- /* prepare the message */
- contract_msg.type = FRSH_MT_NEGOTIATE_CONTRACT;
- contract_msg.val.negotiate_contract.contract = contract;
- /* contact the service thread for contract negotiation */
- if (frsh_service_th_ask_for(frsh_service_th_pid, &contract_msg, &vres_msg) != FRSH_SERVICE_TH_NO_ERROR)
- PERROR_AND_RETURN(FRSH_ERR_INVALID_SCHEDULER_REPLY,
- "can't receive correct answer from the service thread");
- if (vres_msg.error != FRSH_NO_ERROR)
- /* possible return values are listed in the description
- * of the function upward (the one marked with '(*)') */
- PERROR_AND_RETURN(vres_msg.error,
- "can't negotiate the new background contract");
- *vres_id = vres_msg.val.negotiate_contract.vres_id;
- /* create a new thread with the described wrapper
- * as thread code in order to handle the binding to the
- * just created background vres (and to signal us when it's done!)*/
- wp.parent_thread_id = fosa_thread_self();
- wp.thread_id = thread_id; /* directly fill the user provided thread descriptor pointer */
- //wp.pthread_pthread_id = &(thread_id->pthread_id);
- //wp.pthread_linux_pid = &(thread_id->linux_pid);
- //wp.pthread_linux_tid = &(thread_id->linux_tid);
- wp.vres = *vres_id;
- wp.pthread_code = thread_code;
- wp.pthread_arg = (void*) thread_arg;
- /* create the wrapper thread */
- thread_status = fosa_thread_create(NULL, attr, wrapper_pthread_create,(void*) &wp);
- if (thread_status != 0)
- PERROR_AND_RETURN(thread_status,
- "can't create the new background thread");
- /* prepare a suited signal mask and wait for the new
- * thread to acknowledge us it has filled the pointers with the descriptor*/
- //pthread_sigmask(0, NULL, &thread_wait_mask);
- //sigdelset(&thread_wait_mask, FRSH_SCHEDULER_SIGNAL);
- wait_signal = FRSH_SCHEDULER_SIGNAL;
- fosa_set_accepted_signals(&wait_signal, 1);
- /* half a second timeout!! */
- wait_signal_timeout = FOSA_USEC_TO_REL_TIME(500000);
- //if (sigsuspend(&thread_wait_mask) != -1)
- if (fosa_signal_timedwait(&wait_signal, 1, NULL, &wait_signal_info, &wait_signal_timeout) < 0)
- PERROR_AND_RETURN(FRSH_ERR_INTERNAL_ERROR,
- "can't synchronize with the new created background thread");
- if (wait_signal_info.sival_int != FRSH_NO_ERROR)
- PERROR_AND_RETURN(wait_signal_info.sival_int,
- "can't create and bind the new background thread");
- /* restore the signal mask to its original */
- //sigaddset(&thread_wait_mask, FRSH_SCHEDULER_SIGNAL);
- //pthread_sigmask(FRSH_SCHEDULER_SIGNAL, &thread_wait_mask, NULL);
-
- return FRSH_NO_ERROR;
-}
-