c/c++语言开发共享成功swapcontext后返回函数执行时出现段错误

我正在尝试编写一个库来管理使用上下文的线程(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]=""; for (k=0;kthread); AddToBlist(cthread,s); cthread = rhead->thread; rhead = rhead->next; printf("n before swap inside join alln"); //ff printf("btail tid :%dn",(btail->thread)->tid); printf("cthread tid :%dn",cthread->tid); printf("btail thd addr :%pn",btail->thread); printf("cthread addr :%pn",cthread); int tj = swapcontext((btail->thread)->ctextptr, cthread->ctextptr); printf("n after swap tj = %d, cthread tid :%dn",tj,cthread->tid); //ff } // Terminate invoking thread void MyThreadExit(void) { printf("n In thread exit n"); //ff clearB(cthread->tid); //Move threads blocked on current thread to ready queue printf("n clearB done n"); //ff printf("n removing parent (invoking) thread's children n"); //ff if (rhead == NULL) { printf("n ready queue is empty, exiting n"); //ff //cthread = NULL; //setcontext (NULL); } else { cthread = rhead->thread; rhead = rhead->next; printf("cthread tid :%dn",cthread->tid); setcontext (cthread->ctextptr); } } // ****** SEMAPHORE OPERATIONS ****** // Create a semaphore MySemaphore MySemaphoreInit(int initialValue); // Signal a semaphore void MySemaphoreSignal(MySemaphore sem); // Wait on a semaphore void MySemaphoreWait(MySemaphore sem); // Destroy on a semaphore int MySemaphoreDestroy(MySemaphore sem); // ****** CALLS ONLY FOR UNIX PROCESS ****** // Create and run the "main" thread void MyThreadInit(void(*start_funct)(void *), void *args) { tindex = 1; cthread = malloc (sizeof(struct tnode)); memset(cthread, 0, sizeof(struct tnode)); cthread->tid = tindex; cthread->pid = 0; ucontext_t* ctxmain; ctxmain = (ucontext_t *) malloc(sizeof(ucontext_t)); getcontext(ctxmain); char sti[8192]; cthread->ctextptr = (ucontext_t *) malloc(sizeof(ucontext_t)); getcontext(cthread->ctextptr); cthread->ctextptr->uc_stack.ss_sp = sti; cthread->ctextptr->uc_stack.ss_size = sizeof sti; cthread->ctextptr->uc_link = ctxmain; cthread->ctextptr->uc_stack.ss_flags = 0; makecontext(cthread->ctextptr, (void (*)(void))start_funct, 1, args); swapcontext(ctxmain, cthread->ctextptr); } 

这是使用这个库的程序: –

  #include  #include "mythread.h" int n; void t1(void * who) { int i; printf("n checkpoint 2 n"); printf("n who: %d n",(int)who); //sleep(5); printf("t%d startn", (int)who); for (i = 0; i < n; i++) { printf("t%d yieldn", (int)who); printf("n oogaa n"); MyThreadYield(); printf("n boogaa n"); } printf("t%d endn", (int)who); MyThreadExit(); printf("n checkpoint 3 n"); } void t0(void * dummy) { printf("n dummy: %d n",(int)dummy); //sleep(5); printf("n checkpoint 1 n"); MyThreadCreate(t1, (void *)1); printf(" hello 6n"); t1(0); printf("n checkpoint 4 n"); } int main(int argc, char *argv[]) { if (argc != 2) return -1; n = atoi(argv[1]); MyThreadInit(t0, (void*)7); printf("n checkpoint 5 n"); } 

以下是传递参数n = 2的程序的输出: –

  eos$ ./ping.exe 2 dummy: 7 checkpoint 1 hello 6 checkpoint 2 who: 0 t0 start t0 yield oogaa cthread addr :0x1151010 rhead thd addr :0x1151790 rtail thd addr :0x1151010 cthread addr :0x1151790 before swap checkpoint 2 who: 1 t1 start t1 yield oogaa cthread addr :0x1151790 rhead thd addr :0x1151010 rtail thd addr :0x1151790 cthread addr :0x1151010 before swap after swap ty = 0, cthread tid :1 boogaa t0 yield oogaa cthread addr :0x1151010 rhead thd addr :0x1151790 rtail thd addr :0x1151010 cthread addr :0x1151790 before swap after swap ty = 0, cthread tid :2 Segmentation fault (core dumped) 

如您所见,我的调试消息表明地址已正确交换,因此我无法找出segfault的原因。

尝试使用gdb调试它,但我在我的智慧结束,仍然没有任何线索。

任何帮助将非常感谢!

    我能够通过朋友的帮助解决这个问题。 我非常愚蠢和琐碎的错误。 我试图通过本地堆栈将内存分配给上下文,这可能会被杀死并导致问题。 见下面的注释行: –

     //char sti[8192]; //cthread->ctextptr->uc_stack.ss_sp = sti; //cthread->ctextptr->uc_stack.ss_size = sizeof sti; 

    在将上面的行更改为以下行并使用直接分配时,我的代码运行正常。

     cthread->ctextptr->uc_stack.ss_sp = malloc(8192); cthread->ctextptr->uc_stack.ss_size = 8192; 

      以上就是c/c++开发分享成功swapcontext后返回函数执行时出现段错误相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。

      本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

      ctvol管理联系方式QQ:251552304

      本文章地址:https://www.ctvol.com/c-cdevelopment/522564.html

      (0)
      上一篇 2020年12月10日
      下一篇 2020年12月10日

      精彩推荐