我正在尝试编写一个库来管理使用上下文的线程(getcontext,setcontext,makecontext,swapcontext),而不使用pthreads。
函数MyThreadYield(),暂停当前线程上下文,将其发送到就绪队列的末尾,并开始在就绪队列的头部执行线程。
在MyThreadYield()中,我能够通过swapcontext()检索暂停线程的上下文,但是当它返回到函数执行时,我得到一个段错误。
例如: – 假设线程1是init线程,它运行并创建线程2.然后它产生。 现在线程2运行,然后调用yield。 这里swapcontext运行,我可以通过“%p”validation交换是否成功。 但是当它试图从MyThreadYield()返回以恢复线程1的函数运行时,我遇到了seg错误。
这是我的图书馆代码: –
typedef void *MyThread; typedef void *MySemaphore; #include #include #include #include #include // structure of threads struct tnode { ucontext_t* ctextptr; int tid; // own thread id int pid; // parent thread id } ; struct tnode* cthread = NULL; // linked list for ready queue struct rnode { struct tnode* thread; struct rnode* next; } ; struct rnode* rhead = NULL; struct rnode* rtail; static int tindex; // will generate thread id (tid) for new threads // linked list for blocked queue struct bnode { struct tnode* thread; struct bnode* next; int wid[20]; // tid of threads bthread is waiting on //limit is 20 } ; struct bnode* bhead = NULL; struct bnode* btail; int b; // keeps track of size of bacche int bacche[20]; // array to store children of current running thread //Pushes blocked thread into the blocked linked list void AddToBlist (struct tnode* thd , char s[]) { struct bnode* newbie = NULL; newbie = malloc (sizeof(struct bnode)); newbie->thread = thd; int i; for(i=0; iwid[i] = 0; char * pch; i=0; pch = strtok(s," "); //Reference : https://stackoverflow.com/questions/4513316/split-string-in-c-every-white-space while (pch!=NULL) { newbie->wid[i] = atoi(pch); i++; pch = strtok (NULL, " "); } printf("n thread wait array : t"); //ff for(i=0; iwid[i]); //ff newbie->next = NULL; btail = newbie; if(bhead==NULL) { bhead = newbie; } else { struct bnode* current = bhead; while (current->next != NULL) { current = current->next; } current->next = newbie; } } // Scan blocked queue to find a matching thread as specified by id int scanB (int id) { int retval = 0; struct bnode* current = bhead; while (current != NULL) { if((current->thread)->tid == id ) { retval = 1; break; } current = current->next; } return retval; } // Scan blocked queue for parent id listed int scanBP (int id) { int retval = 0; struct bnode* current = bhead; while (current != NULL) { if((current->thread)->pid == id ) { bacche[b] = (current->thread)->tid; b++; retval ++; } current = current->next; } return retval; } // Clears a blocked thread and moves it to ready queue // Reference : https://www.cs.bu.edu/teaching/c/linked-list/delete/ void clearB (int id) { if (bhead==NULL) { //return NULL; } struct bnode* bcur = bhead; struct bnode* bpre = bhead; while (bcur!= NULL) { int i; for(i=0; iwid[i] == id) { bcur->wid[i] = 0; break; } } int k = 0; for(i=0; iwid[i] == 0) k++; } if (k==20) { printf("n thread no longer blocked .... moving to ready queue n"); //ff AddToRlist(bcur->thread); if (bcur == bhead) { struct bnode* temp = bhead; bhead = bhead->next; free(temp); bcur = bhead; bpre = bhead; } else { struct bnode* temp = bcur; bcur = bcur->next; bpre->next = bcur; free(temp); } } else { bpre = bcur; bcur = bcur->next; } } } //Pushes newly created context into the linked list void AddToRlist (struct tnode* thd) { struct rnode* newbie = NULL; newbie = malloc (sizeof(struct rnode)); newbie->thread = thd; newbie->next = NULL; rtail = newbie; if(rhead==NULL) { rhead = newbie; } else { struct rnode* current = rhead; while (current->next != NULL) { current = current->next; } current->next = newbie; } } // Scan ready queue to find a matching thread as specified by id int scanR (int id) { int retval = 0; struct rnode* current = rhead; while (current != NULL) { if((current->thread)->tid == id ) { retval = 1; break; } current = current->next; } return retval; } // Checks for parent id among ready queue elements int scanRP (int id) { int retval = 0; struct rnode* current = rhead; while (current != NULL) { if((current->thread)->pid == id ) { bacche[b] = (current->thread)->tid; b++; retval++; } current = current->next; } return retval; } // ****** THREAD OPERATIONS ****** // Create a new thread. MyThread MyThreadCreate(void(*start_funct)(void *), void *args) { tindex++; struct tnode* tnew = NULL; tnew = malloc(sizeof (struct tnode)); memset(tnew, 0, sizeof(struct tnode)); tnew->tid = tindex; tnew->pid = cthread->tid; char stc[8192]; tnew->ctextptr = (ucontext_t *) malloc(sizeof(ucontext_t)); getcontext(tnew->ctextptr); tnew->ctextptr->uc_stack.ss_sp = stc; tnew->ctextptr->uc_stack.ss_size = sizeof stc; tnew->ctextptr->uc_stack.ss_flags = 0; tnew->ctextptr->uc_link = NULL; makecontext(tnew->ctextptr, (void (*)(void))start_funct, 1, args); AddToRlist(tnew); return((MyThread)tnew); } // Yield invoking thread void MyThreadYield(void) { if (rhead == NULL) { return; } else { printf("cthread addr :%pn",cthread); printf("rhead thd addr :%pn",rhead->thread); AddToRlist(cthread); cthread = rhead->thread; rhead = rhead->next; printf("rtail thd addr :%pn",rtail->thread); printf("cthread addr :%pn",cthread); printf("n before swapn"); //ff int ty = swapcontext((rtail->thread)->ctextptr, cthread->ctextptr); printf("n after swap ty = %d, cthread tid :%dn",ty,cthread->tid); //ff } } // Join with a child thread int MyThreadJoin(MyThread thread) { if (cthread->tid != ((struct tnode*)thread)->pid) { printf("n Join Thread not a child of invoking thread, returning -1 n"); return -1; } int check_rlist = scanR(((struct tnode*)thread)->tid); int check_blist = scanB(((struct tnode*)thread)->tid); if (check_rlist == 0 && check_blist == 0) { printf("n Join Thread seems to have been terminated, returning -1 n"); return -1; } printf ("n Join call successful, proceeding with join operation n"); int wid = ((struct tnode*)thread)->tid; char w[15]; sprintf(w, "%d", wid); AddToBlist(cthread,w); cthread = rhead->thread; rhead = rhead->next; printf("n before swap inside joinn"); //ff int tj = swapcontext((btail->thread)->ctextptr, cthread->ctextptr); printf("n after swap tj = %d, cthread tid :%dn",tj,cthread->tid); //ff } // Join with all children void MyThreadJoinAll(void) { int k; b=0; for(k=0;ktid); int check_blist = scanBP(cthread->tid); if (check_blist == 0 && check_rlist == 0) { printf("n can't find any active children, exiting joinall n"); return; } printf("n generated bacche array : t"); //ff for(k=0;k<20;k++) //ff printf("%dt",bacche[k]); //ff int len; char s[50]="