void *hello(void *t) { ///int *reps = (int*)t; int i = 0; // initialize thread specific data for each thread int* id = (int*)malloc(sizeof(int)); assert(id); *id = mythread_self(); mythread_setspecific(id_key, id); //set name char* name = (char*)malloc(sizeof(char)*MAX_NAME_LENGTH); assert(name); memset(name, '\0', MAX_NAME_LENGTH); sprintf(name, "worker-%d", mythread_self()); mythread_setspecific(name_key,name); // user specific data for (; i < mythread_self(); i++) { printf("Thread-%d:Hello thread:%d\n", mythread_self(), i); sleep(1); mythread_yield(); } printf("Thread specific data for %d thread is %d and worker name is %s\n", mythread_self(), *((int *)mythread_getspecific(id_key)), (char*)mythread_getspecific(name_key)); return NULL; }
void *thread_function(void *arg) { int rc, i; mythread_t thread,childthread ; struct threadValues *value; value = (struct threadValues *)arg; thread=mythread_self(); printf("This is thread %d before yielding\n",thread.tid); for(i=0; i < MAX_KEYS; i++) { printf("\nSettig values %d %d for key %d by thread %d", value->v1, value->v2, i, thread.tid); rc = mythread_setspecific(keys[i], value); if(rc != 0) { printf("\nmythread_setspecific call error for thread = %d", keys[i]); } } rc=mythread_create(&childthread,NULL,&printingfunction,NULL); rc=mythread_yield(); printf("this is thread %d after yield\n",thread.tid); //rc = mythread_yield(); getData(); return NULL; }
int mythread_mutex_lock(mythread_mutex_t *mutex) { int lockstatus; mythread_enter_kernel(); mutex->noofwaitingthreads=mutex->noofwaitingthreads+1; mythread_leave_kernel(); if(mutex->lockvariable==-1)// if the lock was already destroyed then return the error code { return 1; // error code } lockstatus=testandtestandset(&(mutex->lockvariable)); // a lockstatus of 0 denotes a successful acquiring of lock while(lockstatus==1) // if the lock acquiring fails after 100 tries , then the thread is blocked and put in a queue until lock becomes available { mythread_enter_kernel(); mutex->noofblockedthreads=mutex->noofblockedthreads+1; mythread_block((mutex->blocked_threads),0);// actual 0 lockstatus=testandtestandset(&(mutex->lockvariable)); // thread that returns from the block state tries to acquire the lock again } mythread_enter_kernel(); mutex->owner_thread=mythread_self(); mythread_leave_kernel(); return lockstatus; }
void *mythread_getspecific(mythread_key_t key) { int i; struct list_node* start; mythread_t tcb; const void *value; for(i=0; i< tsd_key_counter; i++) { if(globalTSD[i].key == key) { start = globalTSD[i].ptr; tcb = mythread_self(); value = search_lnode(start, tcb); if(value == NULL) { write(1,"\nmythread_getspecific - Thread specific data value is not associated with the key",82); return NULL; } //printf("\nmythread_getspecific - Thread specific data value found with this key - %d", ((mythread_t *) value)->tid); return ((void *)value); } } //if key not found in the global array write(1, "\nmythread_getspecific - key not found in the global array\n",60); return NULL; }
int mythread_leave_kernel(){ mythread_t self = mythread_self(); repeat: if(self->reschedule == 1){ self->reschedule = 0; /* Reschedule here*/ if(mythread_readyq()!=NULL && self->attr.attr == 0){ /*The threads time is up and since there's some thread waiting in readyq, it needs to preempt itself */ mythread_scheduler(); } else{ /*If Ready queue is empty or time is not up, continue executing */ mythread_leave_kernel_nonpreemptive(); } } else{ mythread_leave_kernel_nonpreemptive(); } /* Check again in case of a rescheduling since leaving kernel */ if(self->reschedule == 1){ mythread_enter_kernel(); goto repeat; } return 0; }
void *barrierTest(void* arg){ mythread_enter_kernel(); printf("Going to sleep...%ld\n",mythread_self()); mythread_leave_kernel(); //sleep(5); mythread_barrier_wait(&mybarrier); mythread_enter_kernel(); printf("Moving towards new barrier... %ld\n",mythread_self()); mythread_leave_kernel(); mythread_barrier_wait(&mybarrier); mythread_enter_kernel(); printf("%ld exiting... %ld\n",mythread_self()); mythread_leave_kernel(); mythread_exit(NULL); }
int mythread_scheduler(){ mythread_t self = mythread_self(); /*Limiting number of priority queues to 10 */ if(self->preemptions < 10){ self->preemptions += 1; } self->attr.attr = pow(2,self->preemptions); /*Since preemptions = invocation -1 */ mythread_block(mythread_readyq(),1); return 0; }
void* thread_func(void *args) { int t = 0; char buf[10]; mythread_t self = mythread_self(); sprintf(buf, "%ld", (long) args); mythread_mutex_lock(&mutex); strcat(actualOutput, buf); mythread_mutex_unlock(&mutex); }
void getData() { int i; mythread_t tcb; for(i=0; i < MAX_KEYS; i++) { struct threadValues *value = mythread_getspecific(keys[i]); printf("\nmythread_getspecific call for key = %d, values=%d %d\n", keys[i], value->v1, value->v2); if (value == NULL) printf("\nmythread_setspecific call error for thread = %d", keys[i]); tcb = mythread_self(); } }
/* Thread function */ void *thread_function () { int c = 0; while (1) { if (c < 3000) { if (c%2 == 0) { int k = 1; while(k<100000) //While loops to simulate preemptions by making threads run for longer k++; c++; // Each thread will update this variable } else { int k = 1; while(k<200000) //While loops to simulate preemptions by making threads run for longer k++; c++; } } else break; } mythread_enter_kernel(); printf("Thread with tid %ld has been pre-empted: %d times! \n", mythread_self(), mythread_self()->preemptions); mythread_leave_kernel_nonpreemptive(); }
int mythread_setspecific(mythread_key_t key, const void *value) { int i; lnode* start; lnode* new_lnode; int rc; mythread_t tcb; for(i=0; i < tsd_key_counter; i++) { if((globalTSD[i].key) == key) { tcb = mythread_self(); new_lnode = create_lnode(tcb, value); if(globalTSD[i].ptr == NULL) { globalTSD[i].ptr = new_lnode; rc = 0; } else { start = globalTSD[i].ptr; /*passing tcb and value to check if a value already exists for this thread. *If it does, just change the value in that node and delete the new node */ rc = append_lnode(start, new_lnode, /*key,*/ tcb, value); } if(rc == 0) { //printf("\nmythread_setspecific: value for this thread added successfully with key - %d\n",key); return 0; } else if (rc == 1) { /*if the thread specific data value already existed,then it is updated to the new value*/ printf("\nmythread_setspecific: value for this thread updated with key %d\n",key); return 0; } else { printf("\nmythread_setspecific - EINVAL: Invalid key. Failed to add with key %d\n",key); return -1; } } } write(1,"\nmythread_setspecific - EINVAL: Invalid key\n",45); return -1; }
void myhandler(int signal){ mythread_queue_t rq_head,temp, runq_head; rq_head = *mythread_readyq(); runq_head = *mythread_runq(); temp = runq_head; mythread_t self = mythread_self(); /*Every thread will set its reschudle flag on receiving a signal*/ self->reschedule = 1; if(rq_head != NULL){ (self->attr.attr)--; /*On every signal (SIGALRM/SIGUSR1) the attr which denotes its remaining quanta is decremented This happens only if there is atleast one thread in readyq. */ mythread_enter_kernel(); if(signal == SIGALRM){ do{ if(temp->item != self){ syscall(SYS_tkill, ((mythread_t)(temp->item))->tid, SIGUSR1); } temp = temp ->next; } while(temp!=runq_head); } /*Only one thread will enter the kernel and reschedule the remaining ones which did not enter the kernel. * While doing so, the thread will set the reschedule flag of these threads to 0 * We need to check this condition before letting the threads enter the scheduler via mythread_leave_kernel() */ if(self->reschedule == 0){ mythread_leave_kernel_nonpreemptive(); } else{ mythread_leave_kernel(); } } /*Ready queue is empty so let this thread continue running without any interruptions*/ return; }
/* Uses dispatcher to yeild the next Ready thread */ int mythread_yield() { mythread_t *self_tcb = queue_search_elementbyId(mythread_queue_globalVar, mythread_self().tid); /* Using yield_futex so that no other thread yields when one thread is yielding */ futex_down(&yield_futex); if (__dispatch_thread(self_tcb) == -1) { futex_up(&yield_futex); return 0; } /* Release the yield futex */ futex_up(&yield_futex); /* Sleep till another process wakes us up */ futex_down(&self_tcb->futex); return 0; }
int mythread_mutex_lock (mythread_mutex_t *mutex) { // if mutex is not poinitng to anything valid then return EINVAL if (!mutex) return EINVAL; if (mutex->value == -1) return EINVAL; int retry = 0; while (1) { mythread_enter_kernel(); // check if lock is available for atmost 50 times while ((mutex->value == 1) && (retry < RETRY_MAX)) { retry++; } // if we waited for 50 times and lock still not avaialable then break from he loop and block the current thread. if (retry == RETRY_MAX) { break; } // if lock is avaialable, grab it atomically using compare and swap function if (compare_and_swap (&mutex->value, 1, 0)==0) { // update the current owner to mutex to current thread mutex->thread = mythread_self(); mythread_leave_kernel(); return 0; // success } } // end of while loop // if lock is not available after 50 tries, block the current thread. mythread_block (&mutex->queue, BLOCKED); return 0; // success }
int mythread_init_sched(){ /* Set the new_mask for SIGUSR1 and SIGALRM */ mythread_t self = mythread_self(); self->preemptions = 0; (self->attr).attr = pow(2.0,self->preemptions); sigemptyset(&new_mask); sigaddset(&new_mask,SIGUSR1); sigaddset(&new_mask,SIGALRM); sigprocmask(SIG_UNBLOCK,&new_mask,&old_mask); new_action.sa_handler = myhandler; new_action.sa_mask = new_mask; new_action.sa_flags = 0; /* Install signal handler for SIGUSR1 */ if(sigaction(SIGUSR1,&new_action,&old_action)<0){ perror("Error in installing handler for SIGUSR1\n"); return -1; } /* Install signal handler for SIGALRM */ if(sigaction(SIGALRM,&new_action,&old_action)<0){ perror("Error in installing handler for SIGUSR1\n"); return -1; } if(timer_set == 0){ timer_set = 1; struct itimerval timer; struct timeval timerval; timerval.tv_sec=0; timerval.tv_usec=10000; timer.it_interval=timerval; timer.it_value=timerval; setitimer(ITIMER_REAL, &timer, NULL); } return 0; }
void * printingfunction (void * argument) { mythread_t mythread = mythread_self(); printf("this is printing function %d\n",mythread.tid); }