]>
wirehaze git hosting - ppos.git/blob - ppos/kernel/task.c
1 // PingPongOS - PingPong Operating System
3 /* PEDRO HENRIQUE FRIEDRICH RAMOS : GRR20243133 */
10 /* ------------------------------------------------------------------------- */
11 /* Constants -------------------------------------------------------------- */
13 /* 8 pages = 32 KiB */
14 #define STACK_SIZE (8 * 4096)
16 /* ------------------------------------------------------------------------- */
17 /* Static variables ------------------------------------------------------- */
19 static struct task_t
*task_current
;
20 static struct task_t task_kernel
; /* Is task_kernel like init for ppos? */
22 /* ------------------------------------------------------------------------- */
23 /* Internal functions ----------------------------------------------------- */
25 /* Allocate memory for a task's stack.
27 * The size parameter must be page aligned! */
29 alloc_stack (size_t size
)
32 /* Using mmap () instead of malloc () makes a little bit more sense, since
33 * when a task ends the mapping can be immediately deleted. If we use malloc,
34 * we can't know for sure if the brk will be lowered.
36 * Also, it (probably) makes the stack allocations farther apart, so it's less
37 * likely that a task can corrupt another task's stack by accident, which is
38 * possible since ppos doesn't have virtual memory nor memory protection. */
40 return mmap (/* Let the kernel choose the address for the mapping. */
43 /* Size of the mapping (must be page-aligned). */
47 PROT_READ
| PROT_WRITE
,
49 /* Not shared between (linux) processes.
50 * Not backed by a file. */
51 MAP_PRIVATE
| MAP_ANONYMOUS
,
53 /* No file descriptor. */
60 /* ------------------------------------------------------------------------- */
62 /* Free allocated memory for a task's stack. */
64 free_stack (void *stack
, size_t size
)
66 return munmap (stack
, size
);
69 /* ------------------------------------------------------------------------- */
71 /* Get the next free task id.
73 * Stupid simple implementation, not thread safe! */
78 return ++id
; /* id=0 is reserved for task_kernel */
81 /* ------------------------------------------------------------------------- */
82 /* Exported functions ----------------------------------------------------- */
90 /* ------------------------------------------------------------------------- */
93 task_create (char *name
, void (*entry
) (void *), void *arg
)
98 if (!(task
= malloc (sizeof *task
)))
101 if (!(stack
= alloc_stack (STACK_SIZE
)))
102 goto err_malloc_stack
;
104 task
->id
= get_next_id ();
106 task
->status
= STATUS_READY
;
108 /* Probably not the best way to do this but with this interface and the
109 * current implementation it's the best we can do right now.
111 * We need it for task_switch ().
113 * In a multiprocessor system this doesn't hold up. */
115 task
->parent
= task_current
;
117 if (ctx_create (&task
->context
, entry
, arg
, stack
, STACK_SIZE
))
123 free_stack (stack
, STACK_SIZE
);
130 /* ------------------------------------------------------------------------- */
133 task_destroy (struct task_t
*task
)
135 if (task
->status
!= STATUS_TERMINATED
)
138 if (free_stack (task
->context
.stack
, task
->context
.size
))
139 return ERROR
; /* Probably EINVAL. */
146 /* ------------------------------------------------------------------------- */
149 task_switch (struct task_t
*task
)
152 return task_switch (task_current
->parent
);
154 /* Instructions not clear... */
155 switch (task
->status
)
157 case STATUS_TERMINATED
: /* Switch to task_kernel or to parent? */
158 return task_switch (task_kernel
);
160 case STATUS_RUNNING
: /* Return ERROR or switch to another task? */
164 task_current
->status
= STATUS_SUSPENDED
;
166 task_current
->status
= STATUS_RUNNING
;
168 /* task_current and task are not the same, because if they task->status would
169 * be STATUS_RUNNING, which is handled earlier.
171 * Since that's the only error case for ctx_swap (), we're fine ... */
173 return ctx_swap (&task_current
->context
, &task
->context
);
176 /* ------------------------------------------------------------------------- */
179 task_id (struct task_t
*task
)
182 return task_id (task
->current
);
187 /* ------------------------------------------------------------------------- */
190 task_name (struct task_t
*task
)
193 return task_id (task
->current
);
198 /* ------------------------------------------------------------------------- */