int pthread_create ( pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg ) { int (*real_pthread_create) (pthread_t*, const pthread_attr_t*, void *(*routine)(void *), void*) = dlsym (RTLD_NEXT, "pthread_create"); int (*real_pthread_setaffinity_np) (pthread_t thread, size_t cpusetsize, const cpu_set_t *cpuset) = dlsym (RTLD_NEXT, "pthread_setaffinity_np"); int res; cpu_set_t cpuset; int nbProcessors = getNbProcessorsAvailable (); assert (real_pthread_create != NULL); assert (real_pthread_setaffinity_np != NULL); res = real_pthread_create (thread, attr, start_routine, arg); /* Pinning stuff */ CPU_ZERO(&cpuset); CPU_SET(core, &cpuset); if (real_pthread_setaffinity_np (*thread, sizeof (cpu_set_t), &cpuset) != 0) { fprintf (stderr, "Error: Cannot pin thread %p on core %d\n", thread, core); perror (""); } core++; core %= nbProcessors; return res; }
/* * pthread_create hook */ int reeact_policy_pthread_create(void *thread, void *attr, void *(*start_routine) (void *), void *arg) { #ifdef _REEACT_DEFAULT_POLICY_ return real_pthread_create((pthread_t*)thread, (pthread_attr_t*)attr, start_routine, arg); #else // TODO: add user-policy here return 0; #endif }
//Initialize void myth_init_body(int worker_num,size_t def_stack_size) { myth_init_ex_body(worker_num,def_stack_size); //Create worker threads intptr_t i; for (i=1;i<g_worker_thread_num;i++){ real_pthread_create(&g_envs[i].worker,NULL,myth_worker_thread_fn,(void*)i); } g_envs[0].worker=real_pthread_self(); //Initialize each worker threads myth_worker_thread_fn((void*)(intptr_t)0); }
/** * Interpose |pthread_create()| so that we can use a custom trampoline * function (see above) that initializes rr thread-local data for new * threads. * * This is a wrapper of |pthread_create()|, but not like the ones * below: we don't wrap |pthread_create()| in order to buffer its * syscalls, rather in order to initialize rr thread data. */ int pthread_create(pthread_t* thread, const pthread_attr_t* attr, void* (*start_routine) (void*), void* arg) { struct thread_func_data* data = malloc(sizeof(*data)); void* saved_buffer = buffer; int ret; data->start_routine = start_routine; data->arg = arg; /* Don't let the new thread use our TLS pointer. */ buffer = NULL; ret = real_pthread_create(thread, attr, thread_trampoline, data); buffer = saved_buffer; return ret; }
/* we are implementing these functions only to know when to turn tsafe * on and off. */ int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg) { static int (*real_pthread_create)(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg) = NULL; if (tsafe_inited && tsafe_disabled) { tsafe_on (); } if (real_pthread_create == NULL) { real_pthread_create = _get_real_func_ ("pthread_create"); } return real_pthread_create (thread, attr, start_routine, arg); }
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start) (void *), void *arg){ int ret; char sem_name[100]; int s_id; int sval; int err = 0; int proto = 0; /* This wrapper executes the full code with global lock, even call to real pthread_create */ sem_wait(global_sem); pthread_create_counter[0]++; /* First of all, we need a simulation thread id. Under thread creation bursts could it be no * * free slot is available. This is what we call a proto-thread. It should be enough to wait * * some time till one slot is available. If the wait takes more than 10 seconds, something is * * wrong about the simulation */ while(1){ struct timespec waiting; s_id = get_new_thread_id(); if(s_id < 0){ if(proto == 0){ proto = 1; proto_threads[0]++; printf("WAITING FOR AN SLOT proto_threads: %d\n", proto_threads[0]); } sem_post(global_sem); } else break; err++; pthread_yield(); if(err == 1000){ printf("WARNING: pthread_create wrapper returning EAGAIN!!!\n"); proto_threads[0]--; return -EAGAIN; } waiting.tv_sec = 0; waiting.tv_nsec = 10000000; nanosleep(&waiting, 0); sem_wait(global_sem); } /* Once we got here the simulation thread is not a proto-thread any more */ if(proto) proto_threads[0]--; sim_lib_printf(0, "I GOT AN SLOT: proto_threads: %d\n", proto_threads[0]); /* simulation thread initialization */ /* Most of it is just for debugging except sleep field */ threads_data[s_id].sleep = -1; threads_data[s_id].creation = *current_sim; threads_data[s_id].deletion = 0; threads_data[s_id].last_sleep = 0; threads_data[s_id].never_ending = 0; threads_data[s_id].last_wakeup = 0; threads_data[s_id].wait_time = 0; threads_data[s_id].wait_count = 0; threads_data[s_id].func_addr = (unsigned long)start; threads_data[s_id].pid = getpid(); set_new_thread(s_id); /* Calling real pthread_create is needed at this point. We need pthread_id for linking * * a simulation thread id with a pthread_id. It could happen a fast thread trying to use * * this linking table before an entry has been created for it, but we are aware of this. * * The link is done as one of the last steps because we need to work for leaving all * * stable before the thread starts working with simulation structures. * */ ret = real_pthread_create(thread, attr, start, arg); /* Opening semaphores using simulation thread id */ memset(&sem_name, '\0', 100); sprintf(sem_name, "%s%d", SIM_LOCAL_SEM_PREFIX, s_id); sim_lib_printf(0, "Opening semaphore %s\n", sem_name); thread_sem[s_id] = sem_open(sem_name, 0); if(thread_sem[s_id] == SEM_FAILED){ printf("Error opening semaphore number %d\n", s_id); return -1; } sem_getvalue(thread_sem[s_id], &sval); sim_lib_printf(0, "pthread_create: sval for %s = %d\n", sem_name, sval); memset(&sem_name, '\0', 100); sprintf(sem_name, "%s%d", SIM_LOCAL_SEM_BACK_PREFIX, s_id); sim_lib_printf(0, "Opening semaphore %s\n", sem_name); thread_sem_back[s_id] = sem_open(sem_name, 0); if(thread_sem_back[s_id] == SEM_FAILED){ printf("Error opening semaphore number %d\n", s_id); return -1; } sem_getvalue(thread_sem_back[s_id], &sval); sim_lib_printf(0, "pthread_create: sval for %s = %d\n", sem_name, sval); /* Sometimes previous thread using this semaphore left the wrong value */ while(sval > 1){ sem_wait(thread_sem_back[s_id]); sem_getvalue(thread_sem_back[s_id], &sval); } if(sval == 0) sem_post(thread_sem_back[s_id]); sim_lib_printf(0, "pthread_create: sval for %s = %d\n", sem_name, sval); /* Is this really needed??? */ thread_info_list[s_id].id = s_id; sim_lib_printf(0, "Dentro de wrapper para pthread_create, getting sleep id %d [%lu]\n", thread_info_list[s_id].id , *(thread)); /* This is the important step. After this a thread can work with simulation wrappers */ thread_info_list[s_id].p = *thread; threads_data[s_id].is_new = 1; threads_data[s_id].ptid = *thread; sem_post(global_sem); return ret; }