summaryrefslogtreecommitdiffstats
path: root/mdk-stage1/dietlibc/libpthread/pthread_create.c
blob: b4a4990819bc4caa5b17e8c90085424ebbd97c85 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>

#include <pthread.h>
#include "thread_internal.h"

int pthread_create (pthread_t *thread, const pthread_attr_t *attr,
		void *(*start_routine) (void *), void *arg)
{
  int ret=0;
  _pthread_descr td;
  pthread_attr_t default_attr;

  __THREAD_INIT();

  if (start_routine==0) {
    (*(__errno_location()))=EINVAL;
    return -1;
  }

  td = __thread_get_free();

  if (td) {
    if (!(attr)) {
      pthread_attr_init(&default_attr);
      attr=&default_attr;
    }

    if ((td->policy!=SCHED_OTHER)&&(td->priority==0)) {
      (*(__errno_location()))=EINVAL;
      return -1;
    }

    if (attr->__inheritsched==PTHREAD_INHERIT_SCHED) {
      _pthread_descr this = __thread_self();
      td->policy	= this->policy;
      td->priority	= this->priority;
    } else {
      td->policy	= attr->__schedpolicy;
      td->priority	= attr->__schedparam.sched_priority;
    }

    td->func		= start_routine;
    td->arg		= arg;

    td->detached	= attr->__detachstate;

    td->stack_size	= attr->__stacksize;

    if (!(td->stack_addr)) {
      char *stack=(char*)malloc(td->stack_size);
      if (!(stack)) {
	(*(__errno_location()))=EINVAL;
	return -1;
      }
      td->stack_begin	= stack;
      td->stack_addr	= stack+td->stack_size;
    } else {
      td->stack_begin	= 0;
      td->stack_addr	= attr->__stackaddr;
    }

    ret = signal_manager_thread(td);

    if (ret>1)
      *thread=ret;
    else
      __thread_cleanup(td);
  }
  else
    (*(__errno_location()))=EAGAIN;

  if (ret<2) return -1;
  return ret;
}