<commit_before>#include "thread.h"

#include <assert.h>
#include <stdlib.h>
#include <stdio.h>

#define STACK_SIZE 1<<22

thread * current_thread;

thread * get_current_thread() {
  return current_thread;
}

thread *thread_init() {
  coro *me = coro_init();
  thread *master = (thread*)malloc(sizeof(thread));
  assert(master != NULL);
  master->co = me;
  master->sched = NULL;
  master->next = NULL;
  master->id = 0; // master always id 0
  master->done = 0;
  master->join_head = NULL;
  master->join_tail = NULL;
  current_thread = master;
  return master;
}

scheduler *create_scheduler(thread *master) {
  scheduler *sched = (scheduler*)malloc(sizeof(scheduler));
  assert(sched != NULL);
  sched->ready = NULL;
  sched->tail = NULL;
  sched->wait = NULL;
  sched->wait_tail = NULL;
  sched->master = master;
  sched->nextId = 1; //non-master id starts at 1
  return sched;
}

static void tramp(struct coro *me, void *arg) {
  // Pass control back and forth a few times to get the info we need.
  coro *master = (coro *)arg;
  thread *my_thr = (thread *)coro_invoke(me, master, NULL);
  thread_func f = (thread_func)coro_invoke(me, master, NULL);
  void *f_arg = coro_invoke(me, master, NULL);
  // Next time we're invoked, it'll be for real.
  coro_invoke(me, master, NULL);

  f(my_thr, f_arg);

  // We shouldn't return, but if we do, kill the thread.
  thread_exit(my_thr, NULL);
}

thread *thread_spawn(thread *me, scheduler *sched,
                     thread_func f, void *arg) {
  thread *thr = (thread*)malloc(sizeof(thread));
  thr->co = coro_spawn(me->co, tramp, STACK_SIZE);
  // Pass control to the trampoline a few times quickly to set up
  // the call of <f>.  Could also create a struct with all this data?
  current_thread = thr;
  coro_invoke(me->co, thr->co, (void *)me->co);
  coro_invoke(me->co, thr->co, thr);
  coro_invoke(me->co, thr->co, (void *)f);
  coro_invoke(me->co, thr->co, (void *)arg);
  current_thread = me;
  thr->sched = sched;
  thr->next = NULL;
  thr->join_head = NULL;
  thr->join_tail = NULL;
  thr->done = 0;
  scheduler_assignTid(sched, thr);
  scheduler_enqueue(sched, thr);
  return thr;
}<commit_msg>add assertion that thread_spawn must be called by current_thread only<commit_after>#include "thread.h"

#include <assert.h>
#include <stdlib.h>
#include <stdio.h>

#define STACK_SIZE 1<<22

thread * current_thread;

thread * get_current_thread() {
  return current_thread;
}

thread *thread_init() {
  coro *me = coro_init();
  thread *master = (thread*)malloc(sizeof(thread));
  assert(master != NULL);
  master->co = me;
  master->sched = NULL;
  master->next = NULL;
  master->id = 0; // master always id 0
  master->done = 0;
  master->join_head = NULL;
  master->join_tail = NULL;
  current_thread = master;
  return master;
}

scheduler *create_scheduler(thread *master) {
  scheduler *sched = (scheduler*)malloc(sizeof(scheduler));
  assert(sched != NULL);
  sched->ready = NULL;
  sched->tail = NULL;
  sched->wait = NULL;
  sched->wait_tail = NULL;
  sched->master = master;
  sched->nextId = 1; //non-master id starts at 1
  return sched;
}

static void tramp(struct coro *me, void *arg) {
  // Pass control back and forth a few times to get the info we need.
  coro *master = (coro *)arg;
  thread *my_thr = (thread *)coro_invoke(me, master, NULL);
  thread_func f = (thread_func)coro_invoke(me, master, NULL);
  void *f_arg = coro_invoke(me, master, NULL);
  // Next time we're invoked, it'll be for real.
  coro_invoke(me, master, NULL);

  f(my_thr, f_arg);

  // We shouldn't return, but if we do, kill the thread.
  thread_exit(my_thr, NULL);
}

thread *thread_spawn(thread *me, scheduler *sched,
                     thread_func f, void *arg) {
  assert( current_thread == me );
  thread *thr = (thread*)malloc(sizeof(thread));
  thr->co = coro_spawn(me->co, tramp, STACK_SIZE);
  // Pass control to the trampoline a few times quickly to set up
  // the call of <f>.  Could also create a struct with all this data?
  current_thread = thr;
  coro_invoke(me->co, thr->co, (void *)me->co);
  coro_invoke(me->co, thr->co, thr);
  coro_invoke(me->co, thr->co, (void *)f);
  coro_invoke(me->co, thr->co, (void *)arg);
  current_thread = me;
  thr->sched = sched;
  thr->next = NULL;
  thr->join_head = NULL;
  thr->join_tail = NULL;
  thr->done = 0;
  scheduler_assignTid(sched, thr);
  scheduler_enqueue(sched, thr);
  return thr;
}
{'fraction_non_alphanumeric': 0.14756707594361074, 'fraction_numerical': 0.004092769440654843, 'mean_word_length': 3.7867247007616975, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 69, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3659316', 'n_tokens_mistral': 1608, 'n_tokens_neox': 1583, 'n_words': 448}