1 | /* Start thread. Mach version. |
2 | Copyright (C) 2000-2022 Free Software Foundation, Inc. |
3 | This file is part of the GNU C Library. |
4 | |
5 | The GNU C Library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License as published by the Free Software Foundation; either |
8 | version 2.1 of the License, or (at your option) any later version. |
9 | |
10 | The GNU C Library is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | Lesser General Public License for more details. |
14 | |
15 | You should have received a copy of the GNU Lesser General Public |
16 | License along with the GNU C Library; if not, see |
17 | <https://www.gnu.org/licenses/>. */ |
18 | |
19 | #include <assert.h> |
20 | #include <errno.h> |
21 | #include <string.h> |
22 | |
23 | #include <mach.h> |
24 | |
25 | #include <pt-internal.h> |
26 | |
27 | /* Prepare a wakeup message. */ |
28 | static error_t |
29 | create_wakeupmsg (struct __pthread *thread) |
30 | { |
31 | kern_return_t err; |
32 | |
33 | /* Build wakeup message. */ |
34 | thread->wakeupmsg.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND, 0); |
35 | thread->wakeupmsg.msgh_size = 0; |
36 | |
37 | err = __mach_port_allocate (__mach_task_self (), MACH_PORT_RIGHT_RECEIVE, |
38 | &thread->wakeupmsg.msgh_remote_port); |
39 | if (err) |
40 | return EAGAIN; |
41 | |
42 | thread->wakeupmsg.msgh_local_port = MACH_PORT_NULL; |
43 | thread->wakeupmsg.msgh_seqno = 0; |
44 | thread->wakeupmsg.msgh_id = 0; |
45 | |
46 | err = __mach_port_insert_right (__mach_task_self (), |
47 | thread->wakeupmsg.msgh_remote_port, |
48 | thread->wakeupmsg.msgh_remote_port, |
49 | MACH_MSG_TYPE_MAKE_SEND); |
50 | if (err) |
51 | { |
52 | __mach_port_destroy (__mach_task_self (), |
53 | thread->wakeupmsg.msgh_remote_port); |
54 | return EAGAIN; |
55 | } |
56 | |
57 | /* No need to queue more than one wakeup message on this port. */ |
58 | __mach_port_set_qlimit (__mach_task_self (), |
59 | thread->wakeupmsg.msgh_remote_port, 1); |
60 | |
61 | return 0; |
62 | } |
63 | |
64 | /* Allocate any resouces for THREAD. The new kernel thread should not |
65 | be eligible to be scheduled. */ |
66 | int |
67 | __pthread_thread_alloc (struct __pthread *thread) |
68 | { |
69 | static int do_create; |
70 | error_t err; |
71 | |
72 | err = create_wakeupmsg (thread); |
73 | if (err) |
74 | return err; |
75 | |
76 | if (!do_create) |
77 | { |
78 | assert (__pthread_total == 0); |
79 | thread->kernel_thread = __mach_thread_self (); |
80 | do_create = 1; |
81 | } |
82 | else |
83 | { |
84 | err = __thread_create (__mach_task_self (), &thread->kernel_thread); |
85 | if (err) |
86 | { |
87 | __mach_port_destroy (__mach_task_self (), |
88 | thread->wakeupmsg.msgh_remote_port); |
89 | return EAGAIN; |
90 | } |
91 | } |
92 | |
93 | return 0; |
94 | } |
95 | |