~jsvoboda/helenos/dnsr

1 by Martin Decky
Initial import
1
/*
420.1.3 by Jakub Jermar
Deploy task_hold() and task_release().
2
 * Copyright (c) 2010 Jakub Jermar
1 by Martin Decky
Initial import
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 *
9
 * - Redistributions of source code must retain the above copyright
10
 *   notice, this list of conditions and the following disclaimer.
11
 * - Redistributions in binary form must reproduce the above copyright
12
 *   notice, this list of conditions and the following disclaimer in the
13
 *   documentation and/or other materials provided with the distribution.
14
 * - The name of the author may not be used to endorse or promote products
15
 *   derived from this software without specific prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
 */
28
29
/** @addtogroup genericproc
30
 * @{
31
 */
32
33
/**
34
 * @file
489 by Martin Decky
major code revision
35
 * @brief Thread management functions.
1 by Martin Decky
Initial import
36
 */
37
38
#include <proc/scheduler.h>
39
#include <proc/thread.h>
40
#include <proc/task.h>
41
#include <mm/frame.h>
42
#include <mm/page.h>
43
#include <arch/asm.h>
44
#include <arch/cycle.h>
45
#include <arch.h>
46
#include <synch/spinlock.h>
47
#include <synch/waitq.h>
48
#include <cpu.h>
393 by Martin Decky
rename order() to order_suffix(), make it a generic libc string function in user space
49
#include <str.h>
1 by Martin Decky
Initial import
50
#include <context.h>
51
#include <adt/avl.h>
52
#include <adt/list.h>
53
#include <time/clock.h>
54
#include <time/timeout.h>
1006 by Jakub Jermar
Merge USB support.
55
#include <time/delay.h>
1 by Martin Decky
Initial import
56
#include <config.h>
57
#include <arch/interrupt.h>
58
#include <smp/ipi.h>
59
#include <arch/faddr.h>
60
#include <atomic.h>
61
#include <memstr.h>
62
#include <print.h>
63
#include <mm/slab.h>
64
#include <debug.h>
65
#include <main/uinit.h>
66
#include <syscall/copy.h>
67
#include <errno.h>
68
69
/** Thread states */
305 by Martin Decky
make sure that all statically allocated strings are declared as "const char *"
70
const char *thread_states[] = {
1 by Martin Decky
Initial import
71
	"Invalid",
72
	"Running",
73
	"Sleeping",
74
	"Ready",
75
	"Entering",
76
	"Exiting",
77
	"Lingering"
392 by Martin Decky
export threads to user space
78
};
79
80
typedef struct {
81
	thread_id_t thread_id;
82
	thread_t *thread;
83
} thread_iterator_t;
1 by Martin Decky
Initial import
84
85
/** Lock protecting the threads_tree AVL tree.
86
 *
87
 * For locking rules, see declaration thereof.
489 by Martin Decky
major code revision
88
 *
1 by Martin Decky
Initial import
89
 */
489 by Martin Decky
major code revision
90
IRQ_SPINLOCK_INITIALIZE(threads_lock);
1 by Martin Decky
Initial import
91
92
/** AVL tree of all threads.
93
 *
94
 * When a thread is found in the threads_tree AVL tree, it is guaranteed to
95
 * exist as long as the threads_lock is held.
489 by Martin Decky
major code revision
96
 *
1 by Martin Decky
Initial import
97
 */
489 by Martin Decky
major code revision
98
avltree_t threads_tree;
1 by Martin Decky
Initial import
99
489 by Martin Decky
major code revision
100
IRQ_SPINLOCK_STATIC_INITIALIZE(tidlock);
101
static thread_id_t last_tid = 0;
1 by Martin Decky
Initial import
102
103
static slab_cache_t *thread_slab;
489 by Martin Decky
major code revision
104
1 by Martin Decky
Initial import
105
#ifdef CONFIG_FPU
106
slab_cache_t *fpu_context_slab;
107
#endif
108
109
/** Thread wrapper.
110
 *
111
 * This wrapper is provided to ensure that every thread makes a call to
112
 * thread_exit() when its implementing function returns.
113
 *
114
 * interrupts_disable() is assumed.
115
 *
116
 */
117
static void cushion(void)
118
{
119
	void (*f)(void *) = THREAD->thread_code;
120
	void *arg = THREAD->thread_arg;
121
	THREAD->last_cycle = get_cycle();
489 by Martin Decky
major code revision
122
	
1 by Martin Decky
Initial import
123
	/* This is where each thread wakes up after its creation */
489 by Martin Decky
major code revision
124
	irq_spinlock_unlock(&THREAD->lock, false);
1 by Martin Decky
Initial import
125
	interrupts_enable();
489 by Martin Decky
major code revision
126
	
1 by Martin Decky
Initial import
127
	f(arg);
128
	
129
	/* Accumulate accounting to the task */
489 by Martin Decky
major code revision
130
	irq_spinlock_lock(&THREAD->lock, true);
1 by Martin Decky
Initial import
131
	if (!THREAD->uncounted) {
329.1.4 by Stanislav Kozina
Accounting separated to kernel and user time.
132
		thread_update_accounting(true);
133
		uint64_t ucycles = THREAD->ucycles;
134
		THREAD->ucycles = 0;
135
		uint64_t kcycles = THREAD->kcycles;
136
		THREAD->kcycles = 0;
1 by Martin Decky
Initial import
137
		
489 by Martin Decky
major code revision
138
		irq_spinlock_pass(&THREAD->lock, &TASK->lock);
329.1.4 by Stanislav Kozina
Accounting separated to kernel and user time.
139
		TASK->ucycles += ucycles;
140
		TASK->kcycles += kcycles;
489 by Martin Decky
major code revision
141
		irq_spinlock_unlock(&TASK->lock, true);
1 by Martin Decky
Initial import
142
	} else
489 by Martin Decky
major code revision
143
		irq_spinlock_unlock(&THREAD->lock, true);
1 by Martin Decky
Initial import
144
	
145
	thread_exit();
489 by Martin Decky
major code revision
146
	
147
	/* Not reached */
1 by Martin Decky
Initial import
148
}
149
489 by Martin Decky
major code revision
150
/** Initialization and allocation for thread_t structure
151
 *
152
 */
153
static int thr_constructor(void *obj, unsigned int kmflags)
1 by Martin Decky
Initial import
154
{
489 by Martin Decky
major code revision
155
	thread_t *thread = (thread_t *) obj;
156
	
157
	irq_spinlock_initialize(&thread->lock, "thread_t_lock");
158
	link_initialize(&thread->rq_link);
159
	link_initialize(&thread->wq_link);
160
	link_initialize(&thread->th_link);
161
	
1 by Martin Decky
Initial import
162
	/* call the architecture-specific part of the constructor */
489 by Martin Decky
major code revision
163
	thr_constructor_arch(thread);
1 by Martin Decky
Initial import
164
	
165
#ifdef CONFIG_FPU
166
#ifdef CONFIG_FPU_LAZY
489 by Martin Decky
major code revision
167
	thread->saved_fpu_context = NULL;
168
#else /* CONFIG_FPU_LAZY */
169
	thread->saved_fpu_context = slab_alloc(fpu_context_slab, kmflags);
170
	if (!thread->saved_fpu_context)
1 by Martin Decky
Initial import
171
		return -1;
489 by Martin Decky
major code revision
172
#endif /* CONFIG_FPU_LAZY */
173
#endif /* CONFIG_FPU */
174
	
825.1.75 by Jakub Jermar
Force kernel stacks to be allocated from the low-memory.
175
	/*
176
	 * Allocate the kernel stack from the low-memory to prevent an infinite
177
	 * nesting of TLB-misses when accessing the stack from the part of the
178
	 * TLB-miss handler written in C.
179
	 *
180
	 * Note that low-memory is safe to be used for the stack as it will be
181
	 * covered by the kernel identity mapping, which guarantees not to
182
	 * nest TLB-misses infinitely (either via some hardware mechanism or
183
	 * by the construciton of the assembly-language part of the TLB-miss
184
	 * handler).
185
	 *
186
	 * This restriction can be lifted once each architecture provides
187
	 * a similar guarantee, for example by locking the kernel stack
188
	 * in the TLB whenever it is allocated from the high-memory and the
189
	 * thread is being scheduled to run.
190
	 */
191
	kmflags |= FRAME_LOWMEM;
192
	kmflags &= ~FRAME_HIGHMEM;
1527.1.4 by Martin Decky
cleanup thread_create() and thread_t structure
193
	
489 by Martin Decky
major code revision
194
	thread->kstack = (uint8_t *) frame_alloc(STACK_FRAMES, FRAME_KA | kmflags);
195
	if (!thread->kstack) {
1 by Martin Decky
Initial import
196
#ifdef CONFIG_FPU
489 by Martin Decky
major code revision
197
		if (thread->saved_fpu_context)
198
			slab_free(fpu_context_slab, thread->saved_fpu_context);
1 by Martin Decky
Initial import
199
#endif
200
		return -1;
201
	}
489 by Martin Decky
major code revision
202
	
1 by Martin Decky
Initial import
203
#ifdef CONFIG_UDEBUG
489 by Martin Decky
major code revision
204
	mutex_initialize(&thread->udebug.lock, MUTEX_PASSIVE);
1 by Martin Decky
Initial import
205
#endif
489 by Martin Decky
major code revision
206
	
1 by Martin Decky
Initial import
207
	return 0;
208
}
209
210
/** Destruction of thread_t object */
489 by Martin Decky
major code revision
211
static size_t thr_destructor(void *obj)
1 by Martin Decky
Initial import
212
{
489 by Martin Decky
major code revision
213
	thread_t *thread = (thread_t *) obj;
214
	
1 by Martin Decky
Initial import
215
	/* call the architecture-specific part of the destructor */
489 by Martin Decky
major code revision
216
	thr_destructor_arch(thread);
217
	
218
	frame_free(KA2PA(thread->kstack));
219
	
1 by Martin Decky
Initial import
220
#ifdef CONFIG_FPU
489 by Martin Decky
major code revision
221
	if (thread->saved_fpu_context)
222
		slab_free(fpu_context_slab, thread->saved_fpu_context);
1 by Martin Decky
Initial import
223
#endif
489 by Martin Decky
major code revision
224
	
225
	return 1;  /* One page freed */
1 by Martin Decky
Initial import
226
}
227
228
/** Initialize threads
229
 *
230
 * Initialize kernel threads support.
231
 *
232
 */
233
void thread_init(void)
234
{
235
	THREAD = NULL;
489 by Martin Decky
major code revision
236
	
1 by Martin Decky
Initial import
237
	atomic_set(&nrdy, 0);
1527.1.2 by Martin Decky
unify slab cache naming scheme (according to the type name)
238
	thread_slab = slab_cache_create("thread_t", sizeof(thread_t), 0,
1 by Martin Decky
Initial import
239
	    thr_constructor, thr_destructor, 0);
489 by Martin Decky
major code revision
240
	
1 by Martin Decky
Initial import
241
#ifdef CONFIG_FPU
1527.1.2 by Martin Decky
unify slab cache naming scheme (according to the type name)
242
	fpu_context_slab = slab_cache_create("fpu_context_t",
243
	    sizeof(fpu_context_t), FPU_CONTEXT_ALIGN, NULL, NULL, 0);
1 by Martin Decky
Initial import
244
#endif
489 by Martin Decky
major code revision
245
	
1 by Martin Decky
Initial import
246
	avltree_create(&threads_tree);
247
}
248
1527.1.4 by Martin Decky
cleanup thread_create() and thread_t structure
249
/** Wire thread to the given CPU
250
 *
251
 * @param cpu CPU to wire the thread to.
252
 *
253
 */
254
void thread_wire(thread_t *thread, cpu_t *cpu)
255
{
256
	irq_spinlock_lock(&thread->lock, true);
257
	thread->cpu = cpu;
258
	thread->wired = true;
259
	irq_spinlock_unlock(&thread->lock, true);
260
}
261
1 by Martin Decky
Initial import
262
/** Make thread ready
263
 *
489 by Martin Decky
major code revision
264
 * Switch thread to the ready state.
1 by Martin Decky
Initial import
265
 *
833.1.3 by Martin Decky
* add support for printing uspace stack traces from kernel console
266
 * @param thread Thread to make ready.
1 by Martin Decky
Initial import
267
 *
268
 */
489 by Martin Decky
major code revision
269
void thread_ready(thread_t *thread)
1 by Martin Decky
Initial import
270
{
489 by Martin Decky
major code revision
271
	irq_spinlock_lock(&thread->lock, true);
272
	
833.1.3 by Martin Decky
* add support for printing uspace stack traces from kernel console
273
	ASSERT(thread->state != Ready);
489 by Martin Decky
major code revision
274
	
1527.1.4 by Martin Decky
cleanup thread_create() and thread_t structure
275
	int i = (thread->priority < RQ_COUNT - 1) ?
276
	    ++thread->priority : thread->priority;
489 by Martin Decky
major code revision
277
	
1527.1.4 by Martin Decky
cleanup thread_create() and thread_t structure
278
	cpu_t *cpu;
1527.1.5 by Jakub Jermar
Honour the prohibition of migration also in thread_ready().
279
	if (thread->wired || thread->nomigrate || thread->fpu_context_engaged) {
489 by Martin Decky
major code revision
280
		ASSERT(thread->cpu != NULL);
281
		cpu = thread->cpu;
1527.1.4 by Martin Decky
cleanup thread_create() and thread_t structure
282
	} else
283
		cpu = CPU;
284
	
489 by Martin Decky
major code revision
285
	thread->state = Ready;
286
	
287
	irq_spinlock_pass(&thread->lock, &(cpu->rq[i].lock));
1 by Martin Decky
Initial import
288
	
289
	/*
489 by Martin Decky
major code revision
290
	 * Append thread to respective ready queue
291
	 * on respective processor.
1 by Martin Decky
Initial import
292
	 */
489 by Martin Decky
major code revision
293
	
1043 by Jiri Svoboda
Separate list_t typedef from link_t (kernel part).
294
	list_append(&thread->rq_link, &cpu->rq[i].rq);
489 by Martin Decky
major code revision
295
	cpu->rq[i].n++;
296
	irq_spinlock_unlock(&(cpu->rq[i].lock), true);
297
	
1 by Martin Decky
Initial import
298
	atomic_inc(&nrdy);
489 by Martin Decky
major code revision
299
	// FIXME: Why is the avg value not used
300
	// avg = atomic_get(&nrdy) / config.cpu_active;
1 by Martin Decky
Initial import
301
	atomic_inc(&cpu->nrdy);
302
}
303
304
/** Create new thread
305
 *
306
 * Create a new thread.
307
 *
489 by Martin Decky
major code revision
308
 * @param func      Thread's implementing function.
309
 * @param arg       Thread's implementing function argument.
310
 * @param task      Task to which the thread belongs. The caller must
311
 *                  guarantee that the task won't cease to exist during the
312
 *                  call. The task's lock may not be held.
313
 * @param flags     Thread flags.
314
 * @param name      Symbolic name (a copy is made).
1 by Martin Decky
Initial import
315
 *
489 by Martin Decky
major code revision
316
 * @return New thread's structure on success, NULL on failure.
1 by Martin Decky
Initial import
317
 *
318
 */
319
thread_t *thread_create(void (* func)(void *), void *arg, task_t *task,
1527.1.4 by Martin Decky
cleanup thread_create() and thread_t structure
320
    thread_flags_t flags, const char *name)
1 by Martin Decky
Initial import
321
{
489 by Martin Decky
major code revision
322
	thread_t *thread = (thread_t *) slab_alloc(thread_slab, 0);
323
	if (!thread)
1 by Martin Decky
Initial import
324
		return NULL;
325
	
326
	/* Not needed, but good for debugging */
966 by Martin Decky
cleanup the huge mess related to stacks, their sizes and locations
327
	memsetb(thread->kstack, STACK_SIZE, 0);
489 by Martin Decky
major code revision
328
	
329
	irq_spinlock_lock(&tidlock, true);
330
	thread->tid = ++last_tid;
331
	irq_spinlock_unlock(&tidlock, true);
332
	
333
	context_save(&thread->saved_context);
334
	context_set(&thread->saved_context, FADDR(cushion),
966 by Martin Decky
cleanup the huge mess related to stacks, their sizes and locations
335
	    (uintptr_t) thread->kstack, STACK_SIZE);
489 by Martin Decky
major code revision
336
	
337
	the_initialize((the_t *) thread->kstack);
338
	
339
	ipl_t ipl = interrupts_disable();
340
	thread->saved_context.ipl = interrupts_read();
341
	interrupts_restore(ipl);
342
	
343
	str_cpy(thread->name, THREAD_NAME_BUFLEN, name);
344
	
345
	thread->thread_code = func;
346
	thread->thread_arg = arg;
347
	thread->ticks = -1;
348
	thread->ucycles = 0;
349
	thread->kcycles = 0;
1527.1.4 by Martin Decky
cleanup thread_create() and thread_t structure
350
	thread->uncounted =
351
	    ((flags & THREAD_FLAG_UNCOUNTED) == THREAD_FLAG_UNCOUNTED);
489 by Martin Decky
major code revision
352
	thread->priority = -1;          /* Start in rq[0] */
353
	thread->cpu = NULL;
1527.1.4 by Martin Decky
cleanup thread_create() and thread_t structure
354
	thread->wired = false;
355
	thread->stolen = false;
356
	thread->uspace =
357
	    ((flags & THREAD_FLAG_USPACE) == THREAD_FLAG_USPACE);
358
	
1032 by Jakub Jermar
More lightweight implementation of delay() in kernel.
359
	thread->nomigrate = 0;
489 by Martin Decky
major code revision
360
	thread->state = Entering;
361
	
362
	timeout_initialize(&thread->sleep_timeout);
363
	thread->sleep_interruptible = false;
364
	thread->sleep_queue = NULL;
365
	thread->timeout_pending = false;
366
	
367
	thread->in_copy_from_uspace = false;
368
	thread->in_copy_to_uspace = false;
369
	
370
	thread->interrupted = false;
371
	thread->detached = false;
372
	waitq_initialize(&thread->join_wq);
373
	
374
	thread->task = task;
375
	
1527.1.4 by Martin Decky
cleanup thread_create() and thread_t structure
376
	thread->fpu_context_exists = false;
377
	thread->fpu_context_engaged = false;
489 by Martin Decky
major code revision
378
	
379
	avltree_node_initialize(&thread->threads_tree_node);
380
	thread->threads_tree_node.key = (uintptr_t) thread;
381
	
1 by Martin Decky
Initial import
382
#ifdef CONFIG_UDEBUG
833.2.1 by Martin Decky
as the 'btrace' command depends on udebug, make it optional on CONFIG_UDEBUG
383
	/* Initialize debugging stuff */
384
	thread->btrace = false;
489 by Martin Decky
major code revision
385
	udebug_thread_initialize(&thread->udebug);
1 by Martin Decky
Initial import
386
#endif
489 by Martin Decky
major code revision
387
	
388
	/* Might depend on previous initialization */
389
	thread_create_arch(thread);
390
	
1527.1.4 by Martin Decky
cleanup thread_create() and thread_t structure
391
	if ((flags & THREAD_FLAG_NOATTACH) != THREAD_FLAG_NOATTACH)
489 by Martin Decky
major code revision
392
		thread_attach(thread, task);
393
	
394
	return thread;
1 by Martin Decky
Initial import
395
}
396
397
/** Destroy thread memory structure
398
 *
399
 * Detach thread from all queues, cpus etc. and destroy it.
489 by Martin Decky
major code revision
400
 *
401
 * @param thread  Thread to be destroyed.
402
 * @param irq_res Indicate whether it should unlock thread->lock
403
 *                in interrupts-restore mode.
404
 *
1 by Martin Decky
Initial import
405
 */
489 by Martin Decky
major code revision
406
void thread_destroy(thread_t *thread, bool irq_res)
1 by Martin Decky
Initial import
407
{
515 by Jakub Jermar
Add more *_locked() assertions.
408
	ASSERT(irq_spinlock_locked(&thread->lock));
489 by Martin Decky
major code revision
409
	ASSERT((thread->state == Exiting) || (thread->state == Lingering));
410
	ASSERT(thread->task);
411
	ASSERT(thread->cpu);
412
	
413
	irq_spinlock_lock(&thread->cpu->lock, false);
414
	if (thread->cpu->fpu_owner == thread)
415
		thread->cpu->fpu_owner = NULL;
416
	irq_spinlock_unlock(&thread->cpu->lock, false);
417
	
418
	irq_spinlock_pass(&thread->lock, &threads_lock);
419
	
420
	avltree_delete(&threads_tree, &thread->threads_tree_node);
421
	
422
	irq_spinlock_pass(&threads_lock, &thread->task->lock);
423
	
1 by Martin Decky
Initial import
424
	/*
425
	 * Detach from the containing task.
426
	 */
489 by Martin Decky
major code revision
427
	list_remove(&thread->th_link);
428
	irq_spinlock_unlock(&thread->task->lock, irq_res);
429
	
1 by Martin Decky
Initial import
430
	/*
420.1.3 by Jakub Jermar
Deploy task_hold() and task_release().
431
	 * Drop the reference to the containing task.
1 by Martin Decky
Initial import
432
	 */
489 by Martin Decky
major code revision
433
	task_release(thread->task);
434
	slab_free(thread_slab, thread);
1 by Martin Decky
Initial import
435
}
436
437
/** Make the thread visible to the system.
438
 *
439
 * Attach the thread structure to the current task and make it visible in the
440
 * threads_tree.
441
 *
489 by Martin Decky
major code revision
442
 * @param t    Thread to be attached to the task.
443
 * @param task Task to which the thread is to be attached.
444
 *
1 by Martin Decky
Initial import
445
 */
489 by Martin Decky
major code revision
446
void thread_attach(thread_t *thread, task_t *task)
1 by Martin Decky
Initial import
447
{
448
	/*
449
	 * Attach to the specified task.
450
	 */
489 by Martin Decky
major code revision
451
	irq_spinlock_lock(&task->lock, true);
452
	
420.1.3 by Jakub Jermar
Deploy task_hold() and task_release().
453
	/* Hold a reference to the task. */
454
	task_hold(task);
489 by Martin Decky
major code revision
455
	
1 by Martin Decky
Initial import
456
	/* Must not count kbox thread into lifecount */
1527.1.4 by Martin Decky
cleanup thread_create() and thread_t structure
457
	if (thread->uspace)
1 by Martin Decky
Initial import
458
		atomic_inc(&task->lifecount);
489 by Martin Decky
major code revision
459
	
1043 by Jiri Svoboda
Separate list_t typedef from link_t (kernel part).
460
	list_append(&thread->th_link, &task->threads);
489 by Martin Decky
major code revision
461
	
462
	irq_spinlock_pass(&task->lock, &threads_lock);
463
	
1 by Martin Decky
Initial import
464
	/*
465
	 * Register this thread in the system-wide list.
466
	 */
489 by Martin Decky
major code revision
467
	avltree_insert(&threads_tree, &thread->threads_tree_node);
468
	irq_spinlock_unlock(&threads_lock, true);
1 by Martin Decky
Initial import
469
}
470
471
/** Terminate thread.
472
 *
489 by Martin Decky
major code revision
473
 * End current thread execution and switch it to the exiting state.
474
 * All pending timeouts are executed.
475
 *
1 by Martin Decky
Initial import
476
 */
477
void thread_exit(void)
478
{
1527.1.4 by Martin Decky
cleanup thread_create() and thread_t structure
479
	if (THREAD->uspace) {
1 by Martin Decky
Initial import
480
#ifdef CONFIG_UDEBUG
481
		/* Generate udebug THREAD_E event */
482
		udebug_thread_e_event();
1527.1.4 by Martin Decky
cleanup thread_create() and thread_t structure
483
		
511 by Jiri Svoboda
Make uspace threads stoppable before they exit. This fixes ticket #244.
484
		/*
485
		 * This thread will not execute any code or system calls from
486
		 * now on.
487
		 */
488
		udebug_stoppable_begin();
1 by Martin Decky
Initial import
489
#endif
490
		if (atomic_predec(&TASK->lifecount) == 0) {
491
			/*
492
			 * We are the last userspace thread in the task that
493
			 * still has not exited. With the exception of the
494
			 * moment the task was created, new userspace threads
495
			 * can only be created by threads of the same task.
496
			 * We are safe to perform cleanup.
489 by Martin Decky
major code revision
497
			 *
1 by Martin Decky
Initial import
498
			 */
499
			ipc_cleanup();
500
			futex_cleanup();
501
			LOG("Cleanup of task %" PRIu64" completed.", TASK->taskid);
502
		}
503
	}
489 by Martin Decky
major code revision
504
	
1 by Martin Decky
Initial import
505
restart:
489 by Martin Decky
major code revision
506
	irq_spinlock_lock(&THREAD->lock, true);
507
	if (THREAD->timeout_pending) {
508
		/* Busy waiting for timeouts in progress */
509
		irq_spinlock_unlock(&THREAD->lock, true);
1 by Martin Decky
Initial import
510
		goto restart;
511
	}
512
	
513
	THREAD->state = Exiting;
489 by Martin Decky
major code revision
514
	irq_spinlock_unlock(&THREAD->lock, true);
515
	
1 by Martin Decky
Initial import
516
	scheduler();
489 by Martin Decky
major code revision
517
	
1 by Martin Decky
Initial import
518
	/* Not reached */
489 by Martin Decky
major code revision
519
	while (true);
1 by Martin Decky
Initial import
520
}
521
1032 by Jakub Jermar
More lightweight implementation of delay() in kernel.
522
/** Prevent the current thread from being migrated to another processor. */
523
void thread_migration_disable(void)
524
{
525
	ASSERT(THREAD);
1527.1.4 by Martin Decky
cleanup thread_create() and thread_t structure
526
	
1032 by Jakub Jermar
More lightweight implementation of delay() in kernel.
527
	THREAD->nomigrate++;
528
}
529
530
/** Allow the current thread to be migrated to another processor. */
531
void thread_migration_enable(void)
532
{
533
	ASSERT(THREAD);
534
	ASSERT(THREAD->nomigrate > 0);
1527.1.4 by Martin Decky
cleanup thread_create() and thread_t structure
535
	
536
	if (THREAD->nomigrate > 0)
537
		THREAD->nomigrate--;
1032 by Jakub Jermar
More lightweight implementation of delay() in kernel.
538
}
539
1 by Martin Decky
Initial import
540
/** Thread sleep
541
 *
542
 * Suspend execution of the current thread.
543
 *
544
 * @param sec Number of seconds to sleep.
545
 *
546
 */
547
void thread_sleep(uint32_t sec)
548
{
162 by Martin Decky
fix kernel thread_sleep() not to overflow thread_usleep()
549
	/* Sleep in 1000 second steps to support
550
	   full argument range */
551
	while (sec > 0) {
552
		uint32_t period = (sec > 1000) ? 1000 : sec;
489 by Martin Decky
major code revision
553
		
162 by Martin Decky
fix kernel thread_sleep() not to overflow thread_usleep()
554
		thread_usleep(period * 1000000);
555
		sec -= period;
556
	}
1 by Martin Decky
Initial import
557
}
558
559
/** Wait for another thread to exit.
560
 *
489 by Martin Decky
major code revision
561
 * @param thread Thread to join on exit.
562
 * @param usec   Timeout in microseconds.
563
 * @param flags  Mode of operation.
1 by Martin Decky
Initial import
564
 *
565
 * @return An error code from errno.h or an error code from synch.h.
489 by Martin Decky
major code revision
566
 *
1 by Martin Decky
Initial import
567
 */
489 by Martin Decky
major code revision
568
int thread_join_timeout(thread_t *thread, uint32_t usec, unsigned int flags)
1 by Martin Decky
Initial import
569
{
489 by Martin Decky
major code revision
570
	if (thread == THREAD)
1 by Martin Decky
Initial import
571
		return EINVAL;
489 by Martin Decky
major code revision
572
	
1 by Martin Decky
Initial import
573
	/*
574
	 * Since thread join can only be called once on an undetached thread,
575
	 * the thread pointer is guaranteed to be still valid.
576
	 */
577
	
489 by Martin Decky
major code revision
578
	irq_spinlock_lock(&thread->lock, true);
579
	ASSERT(!thread->detached);
580
	irq_spinlock_unlock(&thread->lock, true);
581
	
582
	return waitq_sleep_timeout(&thread->join_wq, usec, flags);
1 by Martin Decky
Initial import
583
}
584
585
/** Detach thread.
586
 *
833.1.3 by Martin Decky
* add support for printing uspace stack traces from kernel console
587
 * Mark the thread as detached. If the thread is already
588
 * in the Lingering state, deallocate its resources.
1 by Martin Decky
Initial import
589
 *
489 by Martin Decky
major code revision
590
 * @param thread Thread to be detached.
591
 *
1 by Martin Decky
Initial import
592
 */
489 by Martin Decky
major code revision
593
void thread_detach(thread_t *thread)
1 by Martin Decky
Initial import
594
{
595
	/*
596
	 * Since the thread is expected not to be already detached,
597
	 * pointer to it must be still valid.
598
	 */
489 by Martin Decky
major code revision
599
	irq_spinlock_lock(&thread->lock, true);
600
	ASSERT(!thread->detached);
601
	
602
	if (thread->state == Lingering) {
603
		/*
604
		 * Unlock &thread->lock and restore
605
		 * interrupts in thread_destroy().
606
		 */
607
		thread_destroy(thread, true);
1 by Martin Decky
Initial import
608
		return;
609
	} else {
489 by Martin Decky
major code revision
610
		thread->detached = true;
1 by Martin Decky
Initial import
611
	}
489 by Martin Decky
major code revision
612
	
613
	irq_spinlock_unlock(&thread->lock, true);
1 by Martin Decky
Initial import
614
}
615
616
/** Thread usleep
617
 *
618
 * Suspend execution of the current thread.
619
 *
620
 * @param usec Number of microseconds to sleep.
621
 *
622
 */	
623
void thread_usleep(uint32_t usec)
624
{
625
	waitq_t wq;
162 by Martin Decky
fix kernel thread_sleep() not to overflow thread_usleep()
626
	
1 by Martin Decky
Initial import
627
	waitq_initialize(&wq);
162 by Martin Decky
fix kernel thread_sleep() not to overflow thread_usleep()
628
	
1 by Martin Decky
Initial import
629
	(void) waitq_sleep_timeout(&wq, usec, SYNCH_FLAGS_NON_BLOCKING);
630
}
631
632
static bool thread_walker(avltree_node_t *node, void *arg)
633
{
520 by Martin Decky
better printouts for threads
634
	bool *additional = (bool *) arg;
489 by Martin Decky
major code revision
635
	thread_t *thread = avltree_get_instance(node, thread_t, threads_tree_node);
1 by Martin Decky
Initial import
636
	
329.1.26 by Stanislav Kozina
Removed useless cycles sum, using ucycles + kcycles instead.
637
	uint64_t ucycles, kcycles;
638
	char usuffix, ksuffix;
489 by Martin Decky
major code revision
639
	order_suffix(thread->ucycles, &ucycles, &usuffix);
640
	order_suffix(thread->kcycles, &kcycles, &ksuffix);
641
	
834.1.1 by Martin Decky
* improve synchronization in sys_task_set_name()
642
	char *name;
643
	if (str_cmp(thread->name, "uinit") == 0)
644
		name = thread->task->name;
645
	else
646
		name = thread->name;
647
	
1 by Martin Decky
Initial import
648
#ifdef __32_BITS__
520 by Martin Decky
better printouts for threads
649
	if (*additional)
836 by Martin Decky
fix wrong formatting arguments
650
		printf("%-8" PRIu64 " %10p %10p %9" PRIu64 "%c %9" PRIu64 "%c ",
834.1.1 by Martin Decky
* improve synchronization in sys_task_set_name()
651
		    thread->tid, thread->thread_code, thread->kstack,
652
		    ucycles, usuffix, kcycles, ksuffix);
520 by Martin Decky
better printouts for threads
653
	else
836 by Martin Decky
fix wrong formatting arguments
654
		printf("%-8" PRIu64 " %-14s %10p %-8s %10p %-5" PRIu32 "\n",
834.1.1 by Martin Decky
* improve synchronization in sys_task_set_name()
655
		    thread->tid, name, thread, thread_states[thread->state],
966 by Martin Decky
cleanup the huge mess related to stacks, their sizes and locations
656
		    thread->task, thread->task->container);
1 by Martin Decky
Initial import
657
#endif
489 by Martin Decky
major code revision
658
	
1 by Martin Decky
Initial import
659
#ifdef __64_BITS__
520 by Martin Decky
better printouts for threads
660
	if (*additional)
836 by Martin Decky
fix wrong formatting arguments
661
		printf("%-8" PRIu64 " %18p %18p\n"
520 by Martin Decky
better printouts for threads
662
		    "         %9" PRIu64 "%c %9" PRIu64 "%c ",
663
		    thread->tid, thread->thread_code, thread->kstack,
664
		    ucycles, usuffix, kcycles, ksuffix);
665
	else
836 by Martin Decky
fix wrong formatting arguments
666
		printf("%-8" PRIu64 " %-14s %18p %-8s %18p %-5" PRIu32 "\n",
834.1.1 by Martin Decky
* improve synchronization in sys_task_set_name()
667
		    thread->tid, name, thread, thread_states[thread->state],
966 by Martin Decky
cleanup the huge mess related to stacks, their sizes and locations
668
		    thread->task, thread->task->container);
1 by Martin Decky
Initial import
669
#endif
489 by Martin Decky
major code revision
670
	
520 by Martin Decky
better printouts for threads
671
	if (*additional) {
672
		if (thread->cpu)
673
			printf("%-5u", thread->cpu->id);
674
		else
675
			printf("none ");
676
		
677
		if (thread->state == Sleeping) {
1 by Martin Decky
Initial import
678
#ifdef __32_BITS__
520 by Martin Decky
better printouts for threads
679
			printf(" %10p", thread->sleep_queue);
680
#endif
681
			
682
#ifdef __64_BITS__
683
			printf(" %18p", thread->sleep_queue);
684
#endif
685
		}
489 by Martin Decky
major code revision
686
		
520 by Martin Decky
better printouts for threads
687
		printf("\n");
1 by Martin Decky
Initial import
688
	}
489 by Martin Decky
major code revision
689
	
1 by Martin Decky
Initial import
690
	return true;
691
}
692
489 by Martin Decky
major code revision
693
/** Print list of threads debug info
694
 *
520 by Martin Decky
better printouts for threads
695
 * @param additional Print additional information.
696
 *
489 by Martin Decky
major code revision
697
 */
520 by Martin Decky
better printouts for threads
698
void thread_print_list(bool additional)
1 by Martin Decky
Initial import
699
{
700
	/* Messing with thread structures, avoid deadlock */
489 by Martin Decky
major code revision
701
	irq_spinlock_lock(&threads_lock, true);
702
	
703
#ifdef __32_BITS__
520 by Martin Decky
better printouts for threads
704
	if (additional)
834.1.1 by Martin Decky
* improve synchronization in sys_task_set_name()
705
		printf("[id    ] [code    ] [stack   ] [ucycles ] [kcycles ]"
706
		    " [cpu] [waitqueue]\n");
520 by Martin Decky
better printouts for threads
707
	else
708
		printf("[id    ] [name        ] [address ] [state ] [task    ]"
966 by Martin Decky
cleanup the huge mess related to stacks, their sizes and locations
709
		    " [ctn]\n");
1 by Martin Decky
Initial import
710
#endif
489 by Martin Decky
major code revision
711
	
1 by Martin Decky
Initial import
712
#ifdef __64_BITS__
520 by Martin Decky
better printouts for threads
713
	if (additional) {
714
		printf("[id    ] [code            ] [stack           ]\n"
715
		    "         [ucycles ] [kcycles ] [cpu] [waitqueue       ]\n");
716
	} else
717
		printf("[id    ] [name        ] [address         ] [state ]"
966 by Martin Decky
cleanup the huge mess related to stacks, their sizes and locations
718
		    " [task            ] [ctn]\n");
1 by Martin Decky
Initial import
719
#endif
489 by Martin Decky
major code revision
720
	
520 by Martin Decky
better printouts for threads
721
	avltree_walk(&threads_tree, thread_walker, &additional);
489 by Martin Decky
major code revision
722
	
723
	irq_spinlock_unlock(&threads_lock, true);
1 by Martin Decky
Initial import
724
}
725
726
/** Check whether thread exists.
727
 *
728
 * Note that threads_lock must be already held and
729
 * interrupts must be already disabled.
730
 *
489 by Martin Decky
major code revision
731
 * @param thread Pointer to thread.
1 by Martin Decky
Initial import
732
 *
733
 * @return True if thread t is known to the system, false otherwise.
489 by Martin Decky
major code revision
734
 *
1 by Martin Decky
Initial import
735
 */
489 by Martin Decky
major code revision
736
bool thread_exists(thread_t *thread)
1 by Martin Decky
Initial import
737
{
508 by Jakub Jermar
Reflect assumptions about lock and interrupt state in functions themselves.
738
	ASSERT(interrupts_disabled());
739
	ASSERT(irq_spinlock_locked(&threads_lock));
740
489 by Martin Decky
major code revision
741
	avltree_node_t *node =
742
	    avltree_search(&threads_tree, (avltree_key_t) ((uintptr_t) thread));
1 by Martin Decky
Initial import
743
	
744
	return node != NULL;
745
}
746
747
/** Update accounting of current thread.
748
 *
749
 * Note that thread_lock on THREAD must be already held and
750
 * interrupts must be already disabled.
751
 *
489 by Martin Decky
major code revision
752
 * @param user True to update user accounting, false for kernel.
753
 *
1 by Martin Decky
Initial import
754
 */
329.1.4 by Stanislav Kozina
Accounting separated to kernel and user time.
755
void thread_update_accounting(bool user)
1 by Martin Decky
Initial import
756
{
757
	uint64_t time = get_cycle();
508 by Jakub Jermar
Reflect assumptions about lock and interrupt state in functions themselves.
758
759
	ASSERT(interrupts_disabled());
760
	ASSERT(irq_spinlock_locked(&THREAD->lock));
489 by Martin Decky
major code revision
761
	
762
	if (user)
329.1.4 by Stanislav Kozina
Accounting separated to kernel and user time.
763
		THREAD->ucycles += time - THREAD->last_cycle;
489 by Martin Decky
major code revision
764
	else
329.1.4 by Stanislav Kozina
Accounting separated to kernel and user time.
765
		THREAD->kcycles += time - THREAD->last_cycle;
489 by Martin Decky
major code revision
766
	
1 by Martin Decky
Initial import
767
	THREAD->last_cycle = time;
768
}
769
392 by Martin Decky
export threads to user space
770
static bool thread_search_walker(avltree_node_t *node, void *arg)
771
{
772
	thread_t *thread =
773
	    (thread_t *) avltree_get_instance(node, thread_t, threads_tree_node);
774
	thread_iterator_t *iterator = (thread_iterator_t *) arg;
775
	
776
	if (thread->tid == iterator->thread_id) {
777
		iterator->thread = thread;
778
		return false;
779
	}
780
	
781
	return true;
782
}
783
784
/** Find thread structure corresponding to thread ID.
785
 *
786
 * The threads_lock must be already held by the caller of this function and
787
 * interrupts must be disabled.
788
 *
789
 * @param id Thread ID.
790
 *
791
 * @return Thread structure address or NULL if there is no such thread ID.
792
 *
793
 */
794
thread_t *thread_find_by_id(thread_id_t thread_id)
795
{
508 by Jakub Jermar
Reflect assumptions about lock and interrupt state in functions themselves.
796
	ASSERT(interrupts_disabled());
797
	ASSERT(irq_spinlock_locked(&threads_lock));
833.1.3 by Martin Decky
* add support for printing uspace stack traces from kernel console
798
	
392 by Martin Decky
export threads to user space
799
	thread_iterator_t iterator;
800
	
801
	iterator.thread_id = thread_id;
802
	iterator.thread = NULL;
803
	
804
	avltree_walk(&threads_tree, thread_search_walker, (void *) &iterator);
805
	
806
	return iterator.thread;
807
}
808
833.2.1 by Martin Decky
as the 'btrace' command depends on udebug, make it optional on CONFIG_UDEBUG
809
#ifdef CONFIG_UDEBUG
810
833.1.3 by Martin Decky
* add support for printing uspace stack traces from kernel console
811
void thread_stack_trace(thread_id_t thread_id)
812
{
813
	irq_spinlock_lock(&threads_lock, true);
814
	
815
	thread_t *thread = thread_find_by_id(thread_id);
816
	if (thread == NULL) {
817
		printf("No such thread.\n");
818
		irq_spinlock_unlock(&threads_lock, true);
819
		return;
820
	}
821
	
822
	irq_spinlock_lock(&thread->lock, false);
823
	
824
	/*
825
	 * Schedule a stack trace to be printed
826
	 * just before the thread is scheduled next.
827
	 *
828
	 * If the thread is sleeping then try to interrupt
829
	 * the sleep. Any request for printing an uspace stack
830
	 * trace from within the kernel should be always
831
	 * considered a last resort debugging means, therefore
832
	 * forcing the thread's sleep to be interrupted
833
	 * is probably justifiable.
834
	 */
835
	
836
	bool sleeping = false;
837
	istate_t *istate = thread->udebug.uspace_state;
838
	if (istate != NULL) {
839
		printf("Scheduling thread stack trace.\n");
840
		thread->btrace = true;
841
		if (thread->state == Sleeping)
842
			sleeping = true;
843
	} else
844
		printf("Thread interrupt state not available.\n");
845
	
846
	irq_spinlock_unlock(&thread->lock, false);
847
	
848
	if (sleeping)
849
		waitq_interrupt_sleep(thread);
850
	
851
	irq_spinlock_unlock(&threads_lock, true);
852
}
392 by Martin Decky
export threads to user space
853
833.2.1 by Martin Decky
as the 'btrace' command depends on udebug, make it optional on CONFIG_UDEBUG
854
#endif /* CONFIG_UDEBUG */
855
1 by Martin Decky
Initial import
856
/** Process syscall to create new thread.
857
 *
858
 */
749 by Martin Decky
more unification of basic types
859
sysarg_t sys_thread_create(uspace_arg_t *uspace_uarg, char *uspace_name,
1 by Martin Decky
Initial import
860
    size_t name_len, thread_id_t *uspace_thread_id)
861
{
862
	if (name_len > THREAD_NAME_BUFLEN - 1)
863
		name_len = THREAD_NAME_BUFLEN - 1;
489 by Martin Decky
major code revision
864
	
865
	char namebuf[THREAD_NAME_BUFLEN];
866
	int rc = copy_from_uspace(namebuf, uspace_name, name_len);
1 by Martin Decky
Initial import
867
	if (rc != 0)
749 by Martin Decky
more unification of basic types
868
		return (sysarg_t) rc;
489 by Martin Decky
major code revision
869
	
1 by Martin Decky
Initial import
870
	namebuf[name_len] = 0;
489 by Martin Decky
major code revision
871
	
1 by Martin Decky
Initial import
872
	/*
873
	 * In case of failure, kernel_uarg will be deallocated in this function.
874
	 * In case of success, kernel_uarg will be freed in uinit().
875
	 */
489 by Martin Decky
major code revision
876
	uspace_arg_t *kernel_uarg =
877
	    (uspace_arg_t *) malloc(sizeof(uspace_arg_t), 0);
1 by Martin Decky
Initial import
878
	
879
	rc = copy_from_uspace(kernel_uarg, uspace_uarg, sizeof(uspace_arg_t));
880
	if (rc != 0) {
881
		free(kernel_uarg);
749 by Martin Decky
more unification of basic types
882
		return (sysarg_t) rc;
1 by Martin Decky
Initial import
883
	}
489 by Martin Decky
major code revision
884
	
885
	thread_t *thread = thread_create(uinit, kernel_uarg, TASK,
1527.1.4 by Martin Decky
cleanup thread_create() and thread_t structure
886
	    THREAD_FLAG_USPACE | THREAD_FLAG_NOATTACH, namebuf);
489 by Martin Decky
major code revision
887
	if (thread) {
1 by Martin Decky
Initial import
888
		if (uspace_thread_id != NULL) {
489 by Martin Decky
major code revision
889
			rc = copy_to_uspace(uspace_thread_id, &thread->tid,
890
			    sizeof(thread->tid));
1 by Martin Decky
Initial import
891
			if (rc != 0) {
892
				/*
893
				 * We have encountered a failure, but the thread
894
				 * has already been created. We need to undo its
895
				 * creation now.
896
				 */
489 by Martin Decky
major code revision
897
				
1 by Martin Decky
Initial import
898
				/*
899
				 * The new thread structure is initialized, but
900
				 * is still not visible to the system.
901
				 * We can safely deallocate it.
902
				 */
489 by Martin Decky
major code revision
903
				slab_free(thread_slab, thread);
904
				free(kernel_uarg);
905
				
749 by Martin Decky
more unification of basic types
906
				return (sysarg_t) rc;
1 by Martin Decky
Initial import
907
			 }
908
		}
489 by Martin Decky
major code revision
909
		
1 by Martin Decky
Initial import
910
#ifdef CONFIG_UDEBUG
911
		/*
912
		 * Generate udebug THREAD_B event and attach the thread.
913
		 * This must be done atomically (with the debug locks held),
914
		 * otherwise we would either miss some thread or receive
915
		 * THREAD_B events for threads that already existed
916
		 * and could be detected with THREAD_READ before.
917
		 */
489 by Martin Decky
major code revision
918
		udebug_thread_b_event_attach(thread, TASK);
1 by Martin Decky
Initial import
919
#else
489 by Martin Decky
major code revision
920
		thread_attach(thread, TASK);
1 by Martin Decky
Initial import
921
#endif
489 by Martin Decky
major code revision
922
		thread_ready(thread);
923
		
1 by Martin Decky
Initial import
924
		return 0;
925
	} else
926
		free(kernel_uarg);
489 by Martin Decky
major code revision
927
	
749 by Martin Decky
more unification of basic types
928
	return (sysarg_t) ENOMEM;
1 by Martin Decky
Initial import
929
}
930
931
/** Process syscall to terminate thread.
932
 *
933
 */
749 by Martin Decky
more unification of basic types
934
sysarg_t sys_thread_exit(int uspace_status)
1 by Martin Decky
Initial import
935
{
936
	thread_exit();
489 by Martin Decky
major code revision
937
	
1 by Martin Decky
Initial import
938
	/* Unreachable */
939
	return 0;
940
}
941
942
/** Syscall for getting TID.
943
 *
944
 * @param uspace_thread_id Userspace address of 8-byte buffer where to store
945
 * current thread ID.
946
 *
947
 * @return 0 on success or an error code from @ref errno.h.
489 by Martin Decky
major code revision
948
 *
1 by Martin Decky
Initial import
949
 */
749 by Martin Decky
more unification of basic types
950
sysarg_t sys_thread_get_id(thread_id_t *uspace_thread_id)
1 by Martin Decky
Initial import
951
{
952
	/*
953
	 * No need to acquire lock on THREAD because tid
954
	 * remains constant for the lifespan of the thread.
489 by Martin Decky
major code revision
955
	 *
1 by Martin Decky
Initial import
956
	 */
749 by Martin Decky
more unification of basic types
957
	return (sysarg_t) copy_to_uspace(uspace_thread_id, &THREAD->tid,
1 by Martin Decky
Initial import
958
	    sizeof(THREAD->tid));
959
}
960
156.1.2 by Jakub Jermar
Introduce SYS_THREAD_USLEEP and use it to implement usleep() in uspace.
961
/** Syscall wrapper for sleeping. */
749 by Martin Decky
more unification of basic types
962
sysarg_t sys_thread_usleep(uint32_t usec)
156.1.2 by Jakub Jermar
Introduce SYS_THREAD_USLEEP and use it to implement usleep() in uspace.
963
{
162 by Martin Decky
fix kernel thread_sleep() not to overflow thread_usleep()
964
	thread_usleep(usec);
156.1.2 by Jakub Jermar
Introduce SYS_THREAD_USLEEP and use it to implement usleep() in uspace.
965
	return 0;
966
}
967
720.9.407 by Jan Vesely
Implement SYS_THREAD_UDELAY syscall for short delays
968
sysarg_t sys_thread_udelay(uint32_t usec)
969
{
1006 by Jakub Jermar
Merge USB support.
970
	delay(usec);
720.9.407 by Jan Vesely
Implement SYS_THREAD_UDELAY syscall for short delays
971
	return 0;
972
}
973
1 by Martin Decky
Initial import
974
/** @}
975
 */