void test_move_card_should_not_change_stack_empty_stack_coordinates() { struct stack *origin, *destination; struct card *card[2]; card_malloc(&card[0]); card_malloc(&card[1]); card_init(card[0]); card_init(card[1]); card_set(card[0], ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_0_BEGIN_X); card_set(card[1], KING, HEARTS, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_1_BEGIN_X); stack_malloc(&origin); stack_malloc(&destination); stack_init(origin); stack_init(destination); stack_push(&origin, card[0]); stack_push(&destination, card[1]); move_card(&origin, &destination); assert(origin->card->frame->begin_y == MANEUVRE_BEGIN_Y); assert(origin->card->frame->begin_x == MANEUVRE_0_BEGIN_X); stack_free(origin); stack_free(destination); }
void test_move_card_from_non_stack_empty_stack_to_non_stack_empty_stack() { struct stack *origin, *destination; struct card *card[6]; for (int i = 0; i < 6; i++) { card_malloc(&card[i]); card_init(card[i]); card_set(card[i], TWO + i, i % 5, i % 2, 99, 99); } stack_malloc(&origin); stack_malloc(&destination); stack_init(origin); stack_init(destination); for (int i = 0; i < 3; i++) { stack_push(&origin, card[i]); } for (int i = 3; i < 6; i++) { stack_push(&destination, card[i]); } move_card(&origin, &destination); assert(stack_length(origin) == 2); assert(stack_length(destination) == 4); assert(cards_equal(destination->card, card[2])); assert(cards_equal(destination->next->card, card[5])); stack_free(origin); stack_free(destination); }
void test_valid_move_from_stock_to_maneuvre_stacks() { struct stack *stock, *maneuvre_stacks[7]; stack_malloc(&stock); stack_init(stock); card_set(stock->card, ACE, SPADES, EXPOSED, STOCK_BEGIN_Y, STOCK_BEGIN_X); for (int i = 0; i < 7; i++) { stack_malloc(&maneuvre_stacks[i]); stack_init(maneuvre_stacks[i]); } card_set(maneuvre_stacks[0]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_0_BEGIN_X); card_set(maneuvre_stacks[1]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_1_BEGIN_X); card_set(maneuvre_stacks[2]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_2_BEGIN_X); card_set(maneuvre_stacks[3]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_3_BEGIN_X); card_set(maneuvre_stacks[4]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_4_BEGIN_X); card_set(maneuvre_stacks[5]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_5_BEGIN_X); card_set(maneuvre_stacks[6]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_6_BEGIN_X); for (int i = 0; i < 7; i++) { assert(!valid_move(stock, maneuvre_stacks[i])); } stack_free(stock); for (int i = 0; i < 7; i++) { stack_free(maneuvre_stacks[i]); } }
void test_move_card_from_stack_empty_stack_to_non_stack_empty_stack() { struct stack *origin, *destination, *new_origin, *new_destination, *origin_duplicate, *destination_duplicate; struct card *card; card_malloc(&card); card_init(card); card_set(card, ACE, SPADES, EXPOSED, 0, 0); stack_malloc(&origin); stack_malloc(&destination); stack_init(origin); stack_init(destination); new_origin = origin; new_destination = destination; stack_push(&new_destination, card); origin_duplicate = stack_dup(origin); destination_duplicate = stack_dup(destination); move_card(&new_origin, &new_destination); assert(origin == new_origin); assert(stacks_equal(origin, origin_duplicate)); assert(destination == new_destination); assert(stacks_equal(destination, destination_duplicate)); stack_free(origin); stack_free(destination); }
/** * @brief Output moves of an id in a file * * @return 0 If output was NULL * @return 1 Otherwise * */ int identifier_moves_log(Identifier data, FILE *output) { if (output == NULL) return 0; Stack s, s2; stack_alloc(&s); identifier_to_stack(data, &s); stack_alloc(&s2); identifier_to_stack(data, &s2); char strmove[5]; int move = 0, a, b, c, d; fprintf(output, "MOVES : "); while ((move = stack_pop(&s)) != -1) { stack_expand(&a, &b, &c, &d, move); strmove[0] = a + 'a'; strmove[1] = b + '1'; strmove[2] = c + 'a'; strmove[3] = d + '1'; strmove[4] = '\0'; fprintf(output, "%s ", strmove); } fprintf(output, "<-> "); while ((move = stack_pop(&s2)) != -1) { fprintf(output, "%d ", move); } fprintf(output, "\n"); stack_free(&s2); stack_free(&s); return 1; }
void test_valid_move_from_maneuvre_stack_to_waste_pile() { struct stack *waste_pile, *maneuvre_stacks[7]; stack_malloc(&waste_pile); stack_init(waste_pile); card_set(waste_pile->card, ACE, SPADES, EXPOSED, WASTE_PILE_BEGIN_Y, WASTE_PILE_BEGIN_X); for (int i = 0; i < 7; i++) { stack_malloc(&maneuvre_stacks[i]); stack_init(maneuvre_stacks[i]); } card_set(maneuvre_stacks[0]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_0_BEGIN_X); card_set(maneuvre_stacks[1]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_1_BEGIN_X); card_set(maneuvre_stacks[2]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_2_BEGIN_X); card_set(maneuvre_stacks[3]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_3_BEGIN_X); card_set(maneuvre_stacks[4]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_4_BEGIN_X); card_set(maneuvre_stacks[5]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_5_BEGIN_X); card_set(maneuvre_stacks[6]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_6_BEGIN_X); for (int i = 0; i < 7; i++) { assert(!valid_move(maneuvre_stacks[i], waste_pile)); } stack_free(waste_pile); for (int i = 0; i < 7; i++) { stack_free(maneuvre_stacks[i]); } }
int main(void) { int value = 10, v = 11, i; Student s1 = {12, "student1", "addr1"},s2 = {13, "student2","a1"}, s3 = {15, "stu3", "address3"}, *sptr; pStack ps = stack_new(sizeof(Student) + 20); pStack p = stack_new(sizeof(int)); stack_push(p, &value); stack_push(p, &v); printf("%d\n", *((int*)stack_top(p))); stack_pop(p); printf("%d\n", *((int*)stack_top(p))); stack_push(ps, &s1); stack_push(ps, &s2); sptr = (pStudent)stack_top(ps); printf("no: %d, name: %s\n", sptr->no, sptr->addr); stack_pop(ps); stack_push(ps, &s3); sptr = (pStudent)stack_top(ps); printf("no: %d, name: %s\n", sptr->no, sptr->addr); stack_free(ps); for (i = 0; i < 100; i++) { stack_push(p, &i); } for (i = 0; i < 100; i++) { printf("%d ", *((int*)stack_top(p))); stack_pop(p); } stack_free(p); exit(EXIT_SUCCESS); }
int main(int argc, char **argv) { int op; int number; stack_t st; stack_init(&st, INITIAL_STACK_SIZE); while ((op = get_next_operation(stdin, &number)) != OP_STACK_END) { if (op == OP_STACK_PUSH) { stack_push(&st, number); } else if (op == OP_STACK_POP) { if (stack_is_empty(&st)) { printf("POP from empty stack.\n"); } else { printf("%d\n", stack_pop(&st)); } } else { fprintf(stderr, "Unexpected operation.\n"); stack_free(&st); exit(EXIT_FAILURE); } } stack_free(&st); return EXIT_SUCCESS; }
struct stack * type_constrain_ari(struct elt *e1, struct elt *e2) { struct stack *types, *tmp1, *tmp2; // these will modify the type of e1 and e2 to match arithmetic operation. // if possible. if (type_vartype_constrain_ari(e1) == 0) { return NULL; } if (type_vartype_constrain_ari(e2) == 0) { return NULL; } if (e1->elttype == E_REG) { tmp1 = e1->reg->types; } else { tmp1 = stack_new(); stack_push(tmp1, &possible_types[(int)e1->cst->type]); } if (e2->elttype == E_REG) { tmp2 = e2->reg->types; } else { tmp2 = stack_new(); stack_push(tmp2, &possible_types[(int)e2->cst->type]); } types = type_inter(tmp1, tmp2); if (stack_size(types) == 0) { // float + int stack_push(types, &possible_types[FLO_T]); } if (e1->elttype == E_CST) { stack_free(&tmp1, NULL); } if (e2->elttype == E_CST) { stack_free(&tmp2, NULL); } return types; }
void instr_free(void *instruction) { struct instr *i = (struct instr *) instruction; if (i->optype == I_RAW) { free(i->rawllvm); } else if (i->optype == I_CAST) { elt_free(i->res); elt_free(i->tocast); } else if (i->optype == I_CAL) { free(i->fn); stack_free(&i->args, elt_free); stack_free(&i->ret->reg->types, NULL); elt_free(i->ret); } else { // do not free vr it is used in the global hashmap. if (i->er != NULL) { elt_free(i->er); } if (i->e1 != NULL) { elt_free(i->e1); } if (i->e2 != NULL) { elt_free(i->e2); } } free(i); }
void test_valid_move_from_maneuvre_stack_to_foundation_stacks() { struct stack *foundation_stacks[4]; struct stack *maneuvre_stacks[7]; for (int i = 0; i < 4; i++) { stack_malloc(&foundation_stacks[i]); stack_init(foundation_stacks[i]); } card_set(foundation_stacks[0]->card, ACE, SPADES, EXPOSED, FOUNDATION_BEGIN_Y, FOUNDATION_0_BEGIN_X); card_set(foundation_stacks[1]->card, ACE, SPADES, EXPOSED, FOUNDATION_BEGIN_Y, FOUNDATION_1_BEGIN_X); card_set(foundation_stacks[2]->card, ACE, SPADES, EXPOSED, FOUNDATION_BEGIN_Y, FOUNDATION_2_BEGIN_X); card_set(foundation_stacks[3]->card, ACE, SPADES, EXPOSED, FOUNDATION_BEGIN_Y, FOUNDATION_3_BEGIN_X); for (int i = 0; i < 7; i++) { stack_malloc(&maneuvre_stacks[i]); stack_init(maneuvre_stacks[i]); } card_set(maneuvre_stacks[0]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_0_BEGIN_X); card_set(maneuvre_stacks[1]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_1_BEGIN_X); card_set(maneuvre_stacks[2]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_2_BEGIN_X); card_set(maneuvre_stacks[3]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_3_BEGIN_X); card_set(maneuvre_stacks[4]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_4_BEGIN_X); card_set(maneuvre_stacks[5]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_5_BEGIN_X); card_set(maneuvre_stacks[6]->card, ACE, SPADES, EXPOSED, MANEUVRE_BEGIN_Y, MANEUVRE_6_BEGIN_X); for (int i = 0; i < 7; i++) { for (int j = 0; j < 4; j++) { assert(valid_move(maneuvre_stacks[i], foundation_stacks[j])); } } for (int i = 0; i < 4; i++) { stack_free(foundation_stacks[i]); } for (int i = 0; i < 7; i++) { stack_free(maneuvre_stacks[i]); } }
static int type_vartype_constrain_ari(struct elt *e) { int ret = 0; struct stack *tmp, *inter; // TODO: Init this only once at the begining tmp = stack_new(); stack_push(tmp, &possible_types[FLO_T]); stack_push(tmp, &possible_types[INT_T]); if (e->elttype == E_REG) { inter = type_inter(tmp, e->reg->types); ret = stack_size(inter); if (ret != 0) { // replace old stack with the new one reg_settypes(e->reg, inter); } stack_free(&inter, NULL); } else { if (e->cst->type != FLO_T && e->cst->type != INT_T) { ret = 0; } else { ret = 1; } } stack_free(&tmp, NULL); return ret; }
void test_valid_move_from_waste_pile_to_stock() { struct stack *stock, *waste_pile; stack_malloc(&stock); stack_malloc(&waste_pile); stack_init(stock); stack_init(waste_pile); card_set(stock->card, ACE, SPADES, EXPOSED, STOCK_BEGIN_Y, STOCK_BEGIN_X); card_set(waste_pile->card, KING, HEARTS, EXPOSED, WASTE_PILE_BEGIN_Y, WASTE_PILE_BEGIN_X); assert(!valid_move(waste_pile, stock)); stack_free(stock); stack_free(waste_pile); }
/* Removes the element from front of queue */ void queuePop(Queue *queue) { Stack* tmp_ptr = stack(queue->size); while(size(queue->stk_ptr) > 1) { push(tmp_ptr, peek(queue->stk_ptr)); pop(queue->stk_ptr); } stack_free(queue->stk_ptr); Stack* tmp_ptr2 = stack(queue->size); while(!is_empty(tmp_ptr)) { push(tmp_ptr2, peek(tmp_ptr)); pop(tmp_ptr); } stack_free(tmp_ptr); queue->stk_ptr = tmp_ptr2; }
void stack_print(rpn_stack *stack){ rpn_stack *aux1 = stack, *aux2 = NULL; int count = stack_count(stack); while(aux1 != NULL){ stack_push(&aux2, aux1->value); aux1 = aux1->next; } stack_free(&aux1); while(aux2 != NULL){ printf("%i: %Lf\n", count, aux2->value); aux2 = aux2->next; count--; } stack_free(&aux2); }
int main() { int retval; char cont; struct stack *stack; stack = stack_new(STACK_SIZE); cont = 1; while(cont) { retval = interact(stack); switch (retval) { case EXIT_OP: cont = 0; break; case INVALID_CHAR: printf("Invalid char!\n"); break; case STACK_UNDERFLOW: printf("Stack underflow!\n"); break; case STACK_OVERFLOW: printf("Stack overflow!\n"); break; default: continue; } } stack_free(stack); return 0; }
void stack_check(){ printf("Testing Stack Functions\n"); Stack *s; s = stack_init(); assert_i(stack_size(s), 0, "Check Stack Size after init"); stack_push(s, 1, -1); assert_i(stack_size(s), 1, "Check Stack Size after Push"); stack_push(s, 2, -2); assert_i(stack_size(s), 2, "Check Stack Size after Push"); stack_push(s, 3, -3); assert_i(stack_size(s), 3, "Check Stack Size after Push"); int x, y; stack_pop(s, &x, &y); assert_p(x, y, 3, -3, "Check Pop"); assert_i(stack_size(s), 2, "Check Size after Pop"); stack_pop(s, &x, &y); assert_p(x, y, 2, -2, "Check Pop"); assert_i(stack_size(s), 1, "Check Size after Pop"); stack_push(s, 6, -6); assert_i(stack_size(s), 2, "Check Stack Size after Push"); stack_pop(s, &x, &y); assert_p(x, y, 6, -6, "Check Pop"); assert_i(stack_size(s), 1, "Check Size after Pop"); stack_pop(s, &x, &y); assert_p(x, y, 1, -1, "Check Pop"); assert_i(stack_size(s), 0, "Check Size after Pop"); stack_free(s); }
struct instr * istore(struct var *vr, struct elt *elt) { struct instr *i; struct stack *typeinter; if (elt->elttype == E_REG) { typeinter = type_inter(vr->t, elt->reg->types); if (stack_size(typeinter) == 0) { fprintf(stderr, "Error: Incompatible types in assignment.\n"); return NULL; } reg_bind(elt->reg, vr); reg_settypes(elt->reg, typeinter); stack_free(&typeinter, NULL); i = instr_new(I_STO, vr, elt, NULL, NULL); } else { stack_clear(vr->t, NULL); stack_push(vr->t, &possible_types[(int)elt->cst->type]); i = instr_new(I_STO, vr, elt, NULL, NULL); } return i; }
fit_recipe::~fit_recipe() { seed_list_free(seeds_list); fit_parameters_free(parameters); stack_free(stack); delete ms_setup; }
void multi_fit_engine_free(struct multi_fit_engine *f) { int k; if(f->stack_list) { for(k = 0; k < f->samples_number; k++) { if(f->stack_list[k] != NULL) { stack_free(f->stack_list[k]); } } free(f->stack_list); } /* we don't free each spectrum because we are not the owner */ free(f->spectra_list); /* we don't free f->common_parameters and f->private_parameters because multi_fit_engine does not own these data */ assert(f->initialized == 0); free(f); }
void toplevel_obj_free (obj_t *obj) { switch (obj->type) { case TL_TYPE_DISP: disp_free (obj->cont.disp); break; case TL_TYPE_STACK: stack_free (obj->cont.stack); break; case TL_TYPE_STRATEGY: strategy_free (obj->cont.strategy); break; case TL_TYPE_SAMPLE: str_free (obj->cont.sample_info->spectrum_name); free (obj->cont.sample_info->constraints); free (obj->cont.sample_info->individual); free (obj->cont.sample_info); break; case TL_TYPE_MULTI_FIT: multi_fit_info_free (obj->cont.multi_fit); default: /* */ ; } free (obj); }
void stack_destroy(unsigned long extent) { struct stack *esp = STACK_PTR; //get the stack pointer struct stack *to = (struct stack*)extent; struct variable *var; while(esp < to) { /*Pop up the stack */ var = stack_pop(); #ifdef DEBUG if(var->key) { err(0,"Removing variable :%s\n",var->key); } #endif stack_free(var); //free up var esp = STACK_PTR; //reset stack pointer } }
int main(){ /*创建一个默认大小的栈*/ stack_t *st=stack_alloc_default(sizeof(item_t)); item_t arr[MAX_LEN]; /*往栈中插入元素*/ for(int i=0;i<MAX_LEN;i++){ item_t *cur=&arr[i]; cur->key=i; stack_push(st,cur); } /*从栈里弹出元素*/ while(stack_size(st)>=5){ item_t *p=stack_pop(st); printf("%d\n",p->key); } /*先入栈再出栈*/ stack_push(st,&arr[8]); while(stack_size(st)>0){ item_t *p=stack_pop(st); printf("%d\n",p->key); } /*释放栈内存*/ stack_free(st); return 0; }
/* Create a new thread. It should be passed "fcn", a function which * takes two arguments, (the second one is a dummy, always 4). The * first argument is passed in "arg". Returns the TID of the new * thread */ static pid_t create_thread(int (*fcn)(void *), void *arg, void **stack) { pid_t newpid; int flags; void *my_stack; my_stack = stack_alloc(THREAD_STACK_SIZE); /* need SIGCHLD so parent will get that signal when child dies, * else have errors doing a wait */ flags = SIGCHLD | CLONE_THREAD | CLONE_VM | /* CLONE_THREAD => no signal to parent on termination; have to use * CLONE_CHILD_CLEARTID to get that. Since we're using library call * instead of raw system call we don't have child_tidptr argument, * so we set the location in the child itself via set_tid_address(). */ CLONE_CHILD_CLEARTID | CLONE_FS | CLONE_FILES | CLONE_SIGHAND; newpid = clone(fcn, my_stack, flags, arg); /* this is really a tid since we passed CLONE_THREAD: child has same pid as us */ if (newpid == -1) { fprintf(stderr, "smp.c: Error calling clone\n"); stack_free(my_stack, THREAD_STACK_SIZE); return -1; } *stack = my_stack; return newpid; }
int main() { int i; sleeptime.tv_sec = 0; sleeptime.tv_nsec = 10 * 1000 * 1000; /* 10ms */ /* parent remains in own group. creates child who creates a thread group * and then exits them all */ for (i = 0; i < NUM_THREADS; i++) { child_started[i] = false; child_exit[i] = false; } child[0] = create_thread(run, (void *)(long)0, &stack[0], false); assert(child[0] > -1); /* wait for child to start rest of threads */ for (i = 0; i < NUM_THREADS; i++) { while (!child_started[i]) { /* waste some time: FIXME: should use futex */ nanosleep(&sleeptime, NULL); } } child_exit[0] = true; while (!child_done[0]) nanosleep(&sleeptime, NULL); delete_thread(child[0], stack[0]); for (i = 1; i < NUM_THREADS; i++) stack_free(stack[i], THREAD_STACK_SIZE); }
/* Create a new thread. It should be passed "fcn", a function which * takes two arguments, (the second one is a dummy, always 4). The * first argument is passed in "arg". Returns the TID of the new * thread */ static pid_t create_thread(int (*fcn)(void *), void *arg, void **stack, bool same_group) { pid_t newpid; int flags; void *my_stack; my_stack = stack_alloc(THREAD_STACK_SIZE); /* need SIGCHLD so parent will get that signal when child dies, * else have errors doing a wait */ flags = SIGCHLD | CLONE_VM | /* CLONE_THREAD => no signal to parent on termination; have to use * CLONE_CHILD_CLEARTID to get that. Since we're using library call * instead of raw system call we don't have child_tidptr argument, * so we set the location in the child itself via set_tid_address(). */ CLONE_CHILD_CLEARTID | CLONE_FS | CLONE_FILES | CLONE_SIGHAND; if (same_group) flags |= CLONE_THREAD; /* XXX: Using libc clone in the child here really worries me, but it seems * to work. My theory is that the parent has to call clone, which invokes * the loader to fill in the PLT entry, so when the child calls clone it * doesn't go into the loader and avoiding the races like we saw in i#500. */ newpid = clone(fcn, my_stack, flags, arg); /* this is really a tid if we passed CLONE_THREAD: child has same pid as us */ if (newpid == -1) { nolibc_print("smp.c: Error calling clone\n"); stack_free(my_stack, THREAD_STACK_SIZE); return -1; } *stack = my_stack; return newpid; }
void thread_deallocate( thread_t thread) { task_t task; if (thread == THREAD_NULL) return; if (thread_deallocate_internal(thread) > 0) return; ipc_thread_terminate(thread); task = thread->task; #ifdef MACH_BSD { void *ut = thread->uthread; thread->uthread = NULL; uthread_zone_free(ut); } #endif /* MACH_BSD */ task_deallocate(task); if (thread->kernel_stack != 0) stack_free(thread); machine_thread_destroy(thread); zfree(thread_zone, thread); }
int * inorderTraversal(struct TreeNode *root, int *returnSize) { int idx, *list = (int *)malloc(sizeof(int) * 256); /* ~~, implement a list? */ struct TreeNode *node; Stack *stack = stack_new(sizeof(struct TreeNode *)); idx = 0; node = root; while (node != NULL) { stack_push(stack, &node); node = node->left; } while (!stack_is_empty(stack)) { stack_pop(stack, &node); list[idx++] = node->val; node = node->right; while (node != NULL) { stack_push(stack, &node); node = node->left; } } stack_free(stack); *returnSize = idx; return list; }
struct stack * stack_init(int size) { struct stack *stack = NULL; if (size < 1) { return NULL; } stack = malloc(sizeof(*stack)); if (!stack) { goto err; } stack->array = calloc(size, sizeof(int)); if (!stack->array) { goto err; } stack->top = -1; stack->size = size; return stack; err: stack_free(stack); return NULL; }
/* Create a new thread. It should be passed "fcn", a function which * takes two arguments, (the second one is a dummy, always 4). The * first argument is passed in "arg". Returns the PID of the new * thread */ static pid_t create_thread(int (*fcn)(void *), void *arg, void **stack) { pid_t newpid; int flags; void *my_stack; my_stack = stack_alloc(THREAD_STACK_SIZE); /* need SIGCHLD so parent will get that signal when child dies, * else have errors doing a wait */ /* we're not doing CLONE_THREAD => child has its own pid * (the thread.c test tests CLONE_THREAD) */ flags = (SIGCHLD | CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND); newpid = clone(fcn, my_stack, flags, arg, &p_tid, NULL, &c_tid); if (newpid == -1) { print("smp.c: Error calling clone\n"); stack_free(my_stack, THREAD_STACK_SIZE); return -1; } *stack = my_stack; return newpid; }