2 * Copyright (C) 2013, The AROS Development Team
4 * Author: Jason S. McMullan <jason.mcmullan@gmail.com>
6 * Licensed under the AROS PUBLIC LICENSE (APL) Version 1.1
10 #include <aros/debug.h>
11 #include <aros/kernel.h>
12 #include <exec/execbase.h>
14 #include "kernel_base.h"
15 #include "kernel_intern.h"
16 #include "kernel_globals.h"
17 #include "kernel_unix.h"
19 static void *smp_entry(void *threadp)
21 struct KernelBase *KernelBase = getKernelBase();
22 struct PlatformData *pd = KernelBase->kb_PlatformData;
23 struct KrnUnixThread *thread = threadp;
30 cpu = thread - &pd->thread[0];
31 bug("CPU%d: Kernel IPI\n", cpu);
32 pd->iface->pthread_setspecific(pd->key_cpu, &cpu);
34 /* SIGSYS and SIGURG for threads */
36 SIGDELSET(&newset, SIGSYS); /* SysCall-stype */
37 SIGDELSET(&newset, SIGURG); /* IRQ-style */
38 SIGDELSET(&newset, SIGTSTP); /* Disable() */
39 SIGDELSET(&newset, SIGCONT); /* Enable() */
40 pd->iface->sigprocmask(SIG_SETMASK, &newset, NULL);
43 /* Acknowledge that we are ready to go */
44 pd->iface->pthread_mutex_lock(&pd->forbid_mutex);
45 thread->state = STATE_IDLE;
46 pd->iface->pthread_cond_broadcast(&thread->state_cond);
47 pd->iface->pthread_mutex_unlock(&pd->forbid_mutex);
49 bug("CPU%d: Idle\n", cpu);
50 while (thread->hook == NULL);
52 /* Notify that we are running */
53 pd->iface->pthread_mutex_lock(&pd->forbid_mutex);
54 thread->state = STATE_RUNNING;
55 pd->iface->pthread_cond_broadcast(&thread->state_cond);
56 pd->iface->pthread_mutex_unlock(&pd->forbid_mutex);
58 bug("CPU%d: Running hook %p\n", cpu, thread->hook);
59 res = CALLHOOKPKT(thread->hook, &cpu, thread->message);
69 struct KernelBase *KernelBase = getKernelBase();
70 struct PlatformData *pd = KernelBase->kb_PlatformData;
71 struct KernelInterface *iface = pd->iface;
72 sigset_t oldset, newset;
75 /* Initialize the boot CPU's per-thread data */
76 pd->threads = KrnGetCPUCount();
77 pd->thread = AllocMem(sizeof(struct KrnUnixThread)*pd->threads, MEMF_ANY | MEMF_CLEAR);
79 /* Block all signals..
80 * NOTE: For SMP, sigprocmask is actually pointing to pthread_sigmask,
81 * as required for pthread support
83 iface->sigprocmask(0, NULL, &oldset);
87 iface->sigprocmask(SIG_SETMASK, &newset, NULL);
90 pd->forbid_depth = -1;
91 pd->iface->pthread_mutex_init(&pd->forbid_mutex, NULL);
93 pd->iface->pthread_key_create(&pd->key_cpu, NULL);
94 pd->iface->pthread_key_create(&pd->key_storage, NULL);
97 SIGADDSET(&newset, SIGCONT);
99 /* Start all new threads - they will wait for their KrnUnixTLS->CPUId to
102 pd->thread[0].tid = iface->pthread_self();
103 for (cpu = 1; cpu < pd->threads; cpu++) {
105 struct KrnUnixThread *thread = &pd->thread[cpu];
107 #define O_NONBLOCK 04000
109 thread->state = STATE_STOPPED;
110 pd->iface->pthread_cond_init(&thread->state_cond, NULL);
111 pd->iface->pipe2(thread->signal, O_NONBLOCK );
112 err = iface->pthread_create(&thread->tid, NULL, smp_entry, &pd->thread[cpu]);
114 D(bug("CPU%d: Could not start\n", cpu));
116 /* Wait for startup acknowlege */
117 pd->iface->pthread_mutex_lock(&pd->forbid_mutex);
118 while (thread->state != STATE_IDLE) {
119 pd->iface->pthread_cond_wait(&thread->state_cond, &pd->forbid_mutex);
121 pd->iface->pthread_mutex_unlock(&pd->forbid_mutex);
124 /* Restore the signal set for the boot thread */
125 iface->sigprocmask(SIG_SETMASK, &oldset, NULL);