blob: 48d7045eebe8726061f2849da084413ec5927dfc [file] [log] [blame]
Benny Prijono9033e312005-11-21 02:08:39 +00001/* $Id$ */
2/*
Benny Prijonoa771a512007-02-19 01:13:53 +00003 * Copyright (C)2003-2007 Benny Prijono <benny@prijono.org>
Benny Prijono9033e312005-11-21 02:08:39 +00004 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program 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
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19#ifndef __PJ_OS_H__
20#define __PJ_OS_H__
21
22/**
23 * @file os.h
24 * @brief OS dependent functions
25 */
26#include <pj/types.h>
27
28PJ_BEGIN_DECL
29
30/**
31 * @defgroup PJ_OS Operating System Dependent Functionality.
32 * @ingroup PJ
33 */
34
35
Benny Prijono92ac4472006-07-22 13:42:56 +000036/* **************************************************************************/
Benny Prijono9033e312005-11-21 02:08:39 +000037/**
38 * @defgroup PJ_THREAD Threads
39 * @ingroup PJ_OS
40 * @{
41 * This module provides multithreading API.
42 *
43 * \section pj_thread_examples_sec Examples
44 *
45 * For examples, please see:
46 * - \ref page_pjlib_thread_test
47 * - \ref page_pjlib_sleep_test
48 *
49 */
50
51/**
52 * Thread creation flags:
53 * - PJ_THREAD_SUSPENDED: specify that the thread should be created suspended.
54 */
55typedef enum pj_thread_create_flags
56{
57 PJ_THREAD_SUSPENDED = 1
58} pj_thread_create_flags;
59
60
61/**
Benny Prijono9033e312005-11-21 02:08:39 +000062 * Type of thread entry function.
63 */
64typedef int (PJ_THREAD_FUNC pj_thread_proc)(void*);
65
66/**
67 * Size of thread struct.
68 */
69#if !defined(PJ_THREAD_DESC_SIZE)
Benny Prijonod345a652006-07-31 15:10:36 +000070# define PJ_THREAD_DESC_SIZE (64)
Benny Prijono9033e312005-11-21 02:08:39 +000071#endif
72
73/**
74 * Thread structure, to thread's state when the thread is created by external
75 * or native API.
76 */
77typedef long pj_thread_desc[PJ_THREAD_DESC_SIZE];
78
79/**
80 * Get process ID.
81 * @return process ID.
82 */
83PJ_DECL(pj_uint32_t) pj_getpid(void);
84
85/**
86 * Create a new thread.
87 *
88 * @param pool The memory pool from which the thread record
89 * will be allocated from.
90 * @param thread_name The optional name to be assigned to the thread.
91 * @param proc Thread entry function.
92 * @param arg Argument to be passed to the thread entry function.
93 * @param stack_size The size of the stack for the new thread, or ZERO or
94 * PJ_THREAD_DEFAULT_STACK_SIZE to let the
95 * library choose the reasonable size for the stack.
96 * For some systems, the stack will be allocated from
97 * the pool, so the pool must have suitable capacity.
98 * @param flags Flags for thread creation, which is bitmask combination
99 * from enum pj_thread_create_flags.
100 * @param thread Pointer to hold the newly created thread.
101 *
102 * @return PJ_SUCCESS on success, or the error code.
103 */
104PJ_DECL(pj_status_t) pj_thread_create( pj_pool_t *pool,
105 const char *thread_name,
106 pj_thread_proc *proc,
107 void *arg,
108 pj_size_t stack_size,
109 unsigned flags,
110 pj_thread_t **thread );
111
112/**
113 * Register a thread that was created by external or native API to PJLIB.
114 * This function must be called in the context of the thread being registered.
115 * When the thread is created by external function or API call,
116 * it must be 'registered' to PJLIB using pj_thread_register(), so that it can
117 * cooperate with PJLIB's framework. During registration, some data needs to
118 * be maintained, and this data must remain available during the thread's
119 * lifetime.
120 *
121 * @param thread_name The optional name to be assigned to the thread.
122 * @param desc Thread descriptor, which must be available throughout
123 * the lifetime of the thread.
124 * @param thread Pointer to hold the created thread handle.
125 *
126 * @return PJ_SUCCESS on success, or the error code.
127 */
128PJ_DECL(pj_status_t) pj_thread_register ( const char *thread_name,
129 pj_thread_desc desc,
130 pj_thread_t **thread);
131
132/**
Benny Prijonod6b90f52006-08-11 19:25:17 +0000133 * Check if this thread has been registered to PJLIB.
134 *
135 * @return Non-zero if it is registered.
136 */
Benny Prijonoe71c3602006-10-03 17:00:00 +0000137PJ_DECL(pj_bool_t) pj_thread_is_registered(void);
Benny Prijonod6b90f52006-08-11 19:25:17 +0000138
139
140/**
Benny Prijono9033e312005-11-21 02:08:39 +0000141 * Get thread name.
142 *
143 * @param thread The thread handle.
144 *
145 * @return Thread name as null terminated string.
146 */
147PJ_DECL(const char*) pj_thread_get_name(pj_thread_t *thread);
148
149/**
150 * Resume a suspended thread.
151 *
152 * @param thread The thread handle.
153 *
154 * @return zero on success.
155 */
156PJ_DECL(pj_status_t) pj_thread_resume(pj_thread_t *thread);
157
158/**
159 * Get the current thread.
160 *
161 * @return Thread handle of current thread.
162 */
163PJ_DECL(pj_thread_t*) pj_thread_this(void);
164
165/**
Benny Prijono42c5b9e2006-05-10 19:24:40 +0000166 * Join thread, and block the caller thread until the specified thread exits.
167 * If the specified thread has already been dead, or it does not exist,
168 * the function will return immediately with successfull status.
Benny Prijono9033e312005-11-21 02:08:39 +0000169 *
170 * @param thread The thread handle.
171 *
Benny Prijono42c5b9e2006-05-10 19:24:40 +0000172 * @return PJ_SUCCESS on success.
Benny Prijono9033e312005-11-21 02:08:39 +0000173 */
174PJ_DECL(pj_status_t) pj_thread_join(pj_thread_t *thread);
175
176
177/**
178 * Destroy thread and release resources allocated for the thread.
179 * However, the memory allocated for the pj_thread_t itself will only be released
180 * when the pool used to create the thread is destroyed.
181 *
182 * @param thread The thread handle.
183 *
184 * @return zero on success.
185 */
186PJ_DECL(pj_status_t) pj_thread_destroy(pj_thread_t *thread);
187
188
189/**
190 * Put the current thread to sleep for the specified miliseconds.
191 *
192 * @param msec Miliseconds delay.
193 *
194 * @return zero if successfull.
195 */
196PJ_DECL(pj_status_t) pj_thread_sleep(unsigned msec);
197
198/**
199 * @def PJ_CHECK_STACK()
200 * PJ_CHECK_STACK() macro is used to check the sanity of the stack.
201 * The OS implementation may check that no stack overflow occurs, and
202 * it also may collect statistic about stack usage.
203 */
204#if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK!=0
205
206# define PJ_CHECK_STACK() pj_thread_check_stack(__FILE__, __LINE__)
207
208/** @internal
209 * The implementation of stack checking.
210 */
211PJ_DECL(void) pj_thread_check_stack(const char *file, int line);
212
213/** @internal
214 * Get maximum stack usage statistic.
215 */
216PJ_DECL(pj_uint32_t) pj_thread_get_stack_max_usage(pj_thread_t *thread);
217
218/** @internal
219 * Dump thread stack status.
220 */
221PJ_DECL(pj_status_t) pj_thread_get_stack_info(pj_thread_t *thread,
222 const char **file,
223 int *line);
224#else
225
226# define PJ_CHECK_STACK()
227/** pj_thread_get_stack_max_usage() for the thread */
228# define pj_thread_get_stack_max_usage(thread) 0
229/** pj_thread_get_stack_info() for the thread */
230# define pj_thread_get_stack_info(thread,f,l) (*(f)="",*(l)=0)
231#endif /* PJ_OS_HAS_CHECK_STACK */
232
233/**
234 * @}
235 */
236
Benny Prijono92ac4472006-07-22 13:42:56 +0000237/* **************************************************************************/
Benny Prijono9033e312005-11-21 02:08:39 +0000238/**
239 * @defgroup PJ_TLS Thread Local Storage.
240 * @ingroup PJ_OS
241 * @{
242 */
243
244/**
245 * Allocate thread local storage index. The initial value of the variable at
246 * the index is zero.
247 *
248 * @param index Pointer to hold the return value.
249 * @return PJ_SUCCESS on success, or the error code.
250 */
251PJ_DECL(pj_status_t) pj_thread_local_alloc(long *index);
252
253/**
254 * Deallocate thread local variable.
255 *
256 * @param index The variable index.
257 */
258PJ_DECL(void) pj_thread_local_free(long index);
259
260/**
261 * Set the value of thread local variable.
262 *
263 * @param index The index of the variable.
264 * @param value The value.
265 */
266PJ_DECL(pj_status_t) pj_thread_local_set(long index, void *value);
267
268/**
269 * Get the value of thread local variable.
270 *
271 * @param index The index of the variable.
272 * @return The value.
273 */
274PJ_DECL(void*) pj_thread_local_get(long index);
275
276
277/**
278 * @}
279 */
280
281
Benny Prijono92ac4472006-07-22 13:42:56 +0000282/* **************************************************************************/
Benny Prijono9033e312005-11-21 02:08:39 +0000283/**
284 * @defgroup PJ_ATOMIC Atomic Variables
285 * @ingroup PJ_OS
286 * @{
287 *
288 * This module provides API to manipulate atomic variables.
289 *
290 * \section pj_atomic_examples_sec Examples
291 *
292 * For some example codes, please see:
293 * - @ref page_pjlib_atomic_test
294 */
295
296
297/**
298 * Create atomic variable.
299 *
300 * @param pool The pool.
301 * @param initial The initial value of the atomic variable.
302 * @param atomic Pointer to hold the atomic variable upon return.
303 *
304 * @return PJ_SUCCESS on success, or the error code.
305 */
306PJ_DECL(pj_status_t) pj_atomic_create( pj_pool_t *pool,
307 pj_atomic_value_t initial,
308 pj_atomic_t **atomic );
309
310/**
311 * Destroy atomic variable.
312 *
313 * @param atomic_var the atomic variable.
314 *
315 * @return PJ_SUCCESS if success.
316 */
317PJ_DECL(pj_status_t) pj_atomic_destroy( pj_atomic_t *atomic_var );
318
319/**
320 * Set the value of an atomic type, and return the previous value.
321 *
322 * @param atomic_var the atomic variable.
323 * @param value value to be set to the variable.
324 */
325PJ_DECL(void) pj_atomic_set( pj_atomic_t *atomic_var,
326 pj_atomic_value_t value);
327
328/**
329 * Get the value of an atomic type.
330 *
331 * @param atomic_var the atomic variable.
332 *
333 * @return the value of the atomic variable.
334 */
335PJ_DECL(pj_atomic_value_t) pj_atomic_get(pj_atomic_t *atomic_var);
336
337/**
338 * Increment the value of an atomic type.
339 *
340 * @param atomic_var the atomic variable.
341 */
342PJ_DECL(void) pj_atomic_inc(pj_atomic_t *atomic_var);
343
344/**
345 * Increment the value of an atomic type and get the result.
346 *
347 * @param atomic_var the atomic variable.
348 *
349 * @return The incremented value.
350 */
351PJ_DECL(pj_atomic_value_t) pj_atomic_inc_and_get(pj_atomic_t *atomic_var);
352
353/**
354 * Decrement the value of an atomic type.
355 *
356 * @param atomic_var the atomic variable.
357 */
358PJ_DECL(void) pj_atomic_dec(pj_atomic_t *atomic_var);
359
360/**
361 * Decrement the value of an atomic type and get the result.
362 *
363 * @param atomic_var the atomic variable.
364 *
365 * @return The decremented value.
366 */
367PJ_DECL(pj_atomic_value_t) pj_atomic_dec_and_get(pj_atomic_t *atomic_var);
368
369/**
370 * Add a value to an atomic type.
371 *
372 * @param atomic_var The atomic variable.
373 * @param value Value to be added.
374 */
375PJ_DECL(void) pj_atomic_add( pj_atomic_t *atomic_var,
376 pj_atomic_value_t value);
377
378/**
379 * Add a value to an atomic type and get the result.
380 *
381 * @param atomic_var The atomic variable.
382 * @param value Value to be added.
383 *
384 * @return The result after the addition.
385 */
386PJ_DECL(pj_atomic_value_t) pj_atomic_add_and_get( pj_atomic_t *atomic_var,
387 pj_atomic_value_t value);
388
389/**
390 * @}
391 */
392
Benny Prijono92ac4472006-07-22 13:42:56 +0000393/* **************************************************************************/
Benny Prijono9033e312005-11-21 02:08:39 +0000394/**
395 * @defgroup PJ_MUTEX Mutexes.
396 * @ingroup PJ_OS
397 * @{
398 *
399 * Mutex manipulation. Alternatively, application can use higher abstraction
400 * for lock objects, which provides uniform API for all kinds of lock
401 * mechanisms, including mutex. See @ref PJ_LOCK for more information.
402 */
403
404/**
405 * Mutex types:
406 * - PJ_MUTEX_DEFAULT: default mutex type, which is system dependent.
407 * - PJ_MUTEX_SIMPLE: non-recursive mutex.
408 * - PJ_MUTEX_RECURSIVE: recursive mutex.
409 */
410typedef enum pj_mutex_type_e
411{
412 PJ_MUTEX_DEFAULT,
413 PJ_MUTEX_SIMPLE,
Benny Prijono92ac4472006-07-22 13:42:56 +0000414 PJ_MUTEX_RECURSE
Benny Prijono9033e312005-11-21 02:08:39 +0000415} pj_mutex_type_e;
416
417
418/**
419 * Create mutex of the specified type.
420 *
421 * @param pool The pool.
422 * @param name Name to be associated with the mutex (for debugging).
423 * @param type The type of the mutex, of type #pj_mutex_type_e.
424 * @param mutex Pointer to hold the returned mutex instance.
425 *
426 * @return PJ_SUCCESS on success, or the error code.
427 */
428PJ_DECL(pj_status_t) pj_mutex_create(pj_pool_t *pool,
429 const char *name,
430 int type,
431 pj_mutex_t **mutex);
432
433/**
434 * Create simple, non-recursive mutex.
435 * This function is a simple wrapper for #pj_mutex_create to create
436 * non-recursive mutex.
437 *
438 * @param pool The pool.
439 * @param name Mutex name.
440 * @param mutex Pointer to hold the returned mutex instance.
441 *
442 * @return PJ_SUCCESS on success, or the error code.
443 */
444PJ_DECL(pj_status_t) pj_mutex_create_simple( pj_pool_t *pool, const char *name,
445 pj_mutex_t **mutex );
446
447/**
448 * Create recursive mutex.
449 * This function is a simple wrapper for #pj_mutex_create to create
450 * recursive mutex.
451 *
452 * @param pool The pool.
453 * @param name Mutex name.
454 * @param mutex Pointer to hold the returned mutex instance.
455 *
456 * @return PJ_SUCCESS on success, or the error code.
457 */
458PJ_DECL(pj_status_t) pj_mutex_create_recursive( pj_pool_t *pool,
459 const char *name,
460 pj_mutex_t **mutex );
461
462/**
463 * Acquire mutex lock.
464 *
465 * @param mutex The mutex.
466 * @return PJ_SUCCESS on success, or the error code.
467 */
468PJ_DECL(pj_status_t) pj_mutex_lock(pj_mutex_t *mutex);
469
470/**
471 * Release mutex lock.
472 *
473 * @param mutex The mutex.
474 * @return PJ_SUCCESS on success, or the error code.
475 */
476PJ_DECL(pj_status_t) pj_mutex_unlock(pj_mutex_t *mutex);
477
478/**
479 * Try to acquire mutex lock.
480 *
481 * @param mutex The mutex.
482 * @return PJ_SUCCESS on success, or the error code if the
483 * lock couldn't be acquired.
484 */
485PJ_DECL(pj_status_t) pj_mutex_trylock(pj_mutex_t *mutex);
486
487/**
488 * Destroy mutex.
489 *
490 * @param mutex Te mutex.
491 * @return PJ_SUCCESS on success, or the error code.
492 */
493PJ_DECL(pj_status_t) pj_mutex_destroy(pj_mutex_t *mutex);
494
495/**
496 * Determine whether calling thread is owning the mutex (only available when
497 * PJ_DEBUG is set).
498 * @param mutex The mutex.
499 * @return Non-zero if yes.
500 */
501#if defined(PJ_DEBUG) && PJ_DEBUG != 0
502 PJ_DECL(pj_bool_t) pj_mutex_is_locked(pj_mutex_t *mutex);
503#else
504# define pj_mutex_is_locked(mutex) 1
505#endif
506
507/**
508 * @}
509 */
510
Benny Prijono92ac4472006-07-22 13:42:56 +0000511/* **************************************************************************/
Benny Prijono9033e312005-11-21 02:08:39 +0000512/**
Benny Prijono0ca04b62005-12-30 23:50:15 +0000513 * @defgroup PJ_RW_MUTEX Reader/Writer Mutex
514 * @ingroup PJ_OS
515 * @{
516 * Reader/writer mutex is a classic synchronization object where multiple
517 * readers can acquire the mutex, but only a single writer can acquire the
518 * mutex.
519 */
Benny Prijono294c2532006-06-16 16:52:51 +0000520
521/**
522 * Opaque declaration for reader/writer mutex.
523 * Reader/writer mutex is a classic synchronization object where multiple
524 * readers can acquire the mutex, but only a single writer can acquire the
525 * mutex.
526 */
Benny Prijono0ca04b62005-12-30 23:50:15 +0000527typedef struct pj_rwmutex_t pj_rwmutex_t;
528
529/**
530 * Create reader/writer mutex.
531 *
532 * @param pool Pool to allocate memory for the mutex.
533 * @param name Name to be assigned to the mutex.
534 * @param mutex Pointer to receive the newly created mutex.
535 *
536 * @return PJ_SUCCESS on success, or the error code.
537 */
538PJ_DECL(pj_status_t) pj_rwmutex_create(pj_pool_t *pool, const char *name,
539 pj_rwmutex_t **mutex);
540
541/**
542 * Lock the mutex for reading.
543 *
544 * @param mutex The mutex.
545 * @return PJ_SUCCESS on success, or the error code.
546 */
547PJ_DECL(pj_status_t) pj_rwmutex_lock_read(pj_rwmutex_t *mutex);
548
549/**
550 * Lock the mutex for writing.
551 *
552 * @param mutex The mutex.
553 * @return PJ_SUCCESS on success, or the error code.
554 */
555PJ_DECL(pj_status_t) pj_rwmutex_lock_write(pj_rwmutex_t *mutex);
556
557/**
558 * Release read lock.
559 *
560 * @param mutex The mutex.
561 * @return PJ_SUCCESS on success, or the error code.
562 */
563PJ_DECL(pj_status_t) pj_rwmutex_unlock_read(pj_rwmutex_t *mutex);
564
565/**
566 * Release write lock.
567 *
568 * @param mutex The mutex.
569 * @return PJ_SUCCESS on success, or the error code.
570 */
571PJ_DECL(pj_status_t) pj_rwmutex_unlock_write(pj_rwmutex_t *mutex);
572
573/**
574 * Destroy reader/writer mutex.
575 *
576 * @param mutex The mutex.
577 * @return PJ_SUCCESS on success, or the error code.
578 */
579PJ_DECL(pj_status_t) pj_rwmutex_destroy(pj_rwmutex_t *mutex);
580
581
582/**
583 * @}
584 */
585
586
Benny Prijono92ac4472006-07-22 13:42:56 +0000587/* **************************************************************************/
Benny Prijono0ca04b62005-12-30 23:50:15 +0000588/**
Benny Prijono9033e312005-11-21 02:08:39 +0000589 * @defgroup PJ_CRIT_SEC Critical sections.
590 * @ingroup PJ_OS
591 * @{
592 * Critical section protection can be used to protect regions where:
593 * - mutual exclusion protection is needed.
594 * - it's rather too expensive to create a mutex.
595 * - the time spent in the region is very very brief.
596 *
597 * Critical section is a global object, and it prevents any threads from
598 * entering any regions that are protected by critical section once a thread
599 * is already in the section.
600 *
601 * Critial section is \a not recursive!
602 *
603 * Application <b>MUST NOT</b> call any functions that may cause current
604 * thread to block (such as allocating memory, performing I/O, locking mutex,
605 * etc.) while holding the critical section.
606 */
607/**
608 * Enter critical section.
609 */
610PJ_DECL(void) pj_enter_critical_section(void);
611
612/**
613 * Leave critical section.
614 */
615PJ_DECL(void) pj_leave_critical_section(void);
616
617/**
618 * @}
619 */
620
Benny Prijono92ac4472006-07-22 13:42:56 +0000621/* **************************************************************************/
Benny Prijono9033e312005-11-21 02:08:39 +0000622#if defined(PJ_HAS_SEMAPHORE) && PJ_HAS_SEMAPHORE != 0
623/**
624 * @defgroup PJ_SEM Semaphores.
625 * @ingroup PJ_OS
626 * @{
627 *
628 * This module provides abstraction for semaphores, where available.
629 */
630
631/**
632 * Create semaphore.
633 *
634 * @param pool The pool.
635 * @param name Name to be assigned to the semaphore (for logging purpose)
636 * @param initial The initial count of the semaphore.
637 * @param max The maximum count of the semaphore.
638 * @param sem Pointer to hold the semaphore created.
639 *
640 * @return PJ_SUCCESS on success, or the error code.
641 */
642PJ_DECL(pj_status_t) pj_sem_create( pj_pool_t *pool,
643 const char *name,
644 unsigned initial,
645 unsigned max,
646 pj_sem_t **sem);
647
648/**
649 * Wait for semaphore.
650 *
651 * @param sem The semaphore.
652 *
653 * @return PJ_SUCCESS on success, or the error code.
654 */
655PJ_DECL(pj_status_t) pj_sem_wait(pj_sem_t *sem);
656
657/**
658 * Try wait for semaphore.
659 *
660 * @param sem The semaphore.
661 *
662 * @return PJ_SUCCESS on success, or the error code.
663 */
664PJ_DECL(pj_status_t) pj_sem_trywait(pj_sem_t *sem);
665
666/**
667 * Release semaphore.
668 *
669 * @param sem The semaphore.
670 *
671 * @return PJ_SUCCESS on success, or the error code.
672 */
673PJ_DECL(pj_status_t) pj_sem_post(pj_sem_t *sem);
674
675/**
676 * Destroy semaphore.
677 *
678 * @param sem The semaphore.
679 *
680 * @return PJ_SUCCESS on success, or the error code.
681 */
682PJ_DECL(pj_status_t) pj_sem_destroy(pj_sem_t *sem);
683
684/**
685 * @}
686 */
687#endif /* PJ_HAS_SEMAPHORE */
688
689
Benny Prijono92ac4472006-07-22 13:42:56 +0000690/* **************************************************************************/
Benny Prijono9033e312005-11-21 02:08:39 +0000691#if defined(PJ_HAS_EVENT_OBJ) && PJ_HAS_EVENT_OBJ != 0
692/**
693 * @defgroup PJ_EVENT Event Object.
694 * @ingroup PJ_OS
695 * @{
696 *
697 * This module provides abstraction to event object (e.g. Win32 Event) where
698 * available. Event objects can be used for synchronization among threads.
699 */
700
701/**
702 * Create event object.
703 *
704 * @param pool The pool.
705 * @param name The name of the event object (for logging purpose).
706 * @param manual_reset Specify whether the event is manual-reset
707 * @param initial Specify the initial state of the event object.
708 * @param event Pointer to hold the returned event object.
709 *
710 * @return event handle, or NULL if failed.
711 */
712PJ_DECL(pj_status_t) pj_event_create(pj_pool_t *pool, const char *name,
713 pj_bool_t manual_reset, pj_bool_t initial,
714 pj_event_t **event);
715
716/**
717 * Wait for event to be signaled.
718 *
719 * @param event The event object.
720 *
721 * @return zero if successfull.
722 */
723PJ_DECL(pj_status_t) pj_event_wait(pj_event_t *event);
724
725/**
726 * Try wait for event object to be signalled.
727 *
728 * @param event The event object.
729 *
730 * @return zero if successfull.
731 */
732PJ_DECL(pj_status_t) pj_event_trywait(pj_event_t *event);
733
734/**
735 * Set the event object state to signaled. For auto-reset event, this
736 * will only release the first thread that are waiting on the event. For
737 * manual reset event, the state remains signaled until the event is reset.
738 * If there is no thread waiting on the event, the event object state
739 * remains signaled.
740 *
741 * @param event The event object.
742 *
743 * @return zero if successfull.
744 */
745PJ_DECL(pj_status_t) pj_event_set(pj_event_t *event);
746
747/**
748 * Set the event object to signaled state to release appropriate number of
749 * waiting threads and then reset the event object to non-signaled. For
750 * manual-reset event, this function will release all waiting threads. For
751 * auto-reset event, this function will only release one waiting thread.
752 *
753 * @param event The event object.
754 *
755 * @return zero if successfull.
756 */
757PJ_DECL(pj_status_t) pj_event_pulse(pj_event_t *event);
758
759/**
760 * Set the event object state to non-signaled.
761 *
762 * @param event The event object.
763 *
764 * @return zero if successfull.
765 */
766PJ_DECL(pj_status_t) pj_event_reset(pj_event_t *event);
767
768/**
769 * Destroy the event object.
770 *
771 * @param event The event object.
772 *
773 * @return zero if successfull.
774 */
775PJ_DECL(pj_status_t) pj_event_destroy(pj_event_t *event);
776
777/**
778 * @}
779 */
780#endif /* PJ_HAS_EVENT_OBJ */
781
Benny Prijono92ac4472006-07-22 13:42:56 +0000782/* **************************************************************************/
Benny Prijono9033e312005-11-21 02:08:39 +0000783/**
784 * @addtogroup PJ_TIME Time Data Type and Manipulation.
785 * @ingroup PJ_OS
786 * @{
787 * This module provides API for manipulating time.
788 *
789 * \section pj_time_examples_sec Examples
790 *
791 * For examples, please see:
792 * - \ref page_pjlib_sleep_test
793 */
794
795/**
796 * Get current time of day in local representation.
797 *
798 * @param tv Variable to store the result.
799 *
800 * @return zero if successfull.
801 */
802PJ_DECL(pj_status_t) pj_gettimeofday(pj_time_val *tv);
803
804
805/**
806 * Parse time value into date/time representation.
807 *
808 * @param tv The time.
809 * @param pt Variable to store the date time result.
810 *
811 * @return zero if successfull.
812 */
813PJ_DECL(pj_status_t) pj_time_decode(const pj_time_val *tv, pj_parsed_time *pt);
814
815/**
816 * Encode date/time to time value.
817 *
818 * @param pt The date/time.
819 * @param tv Variable to store time value result.
820 *
821 * @return zero if successfull.
822 */
823PJ_DECL(pj_status_t) pj_time_encode(const pj_parsed_time *pt, pj_time_val *tv);
824
825/**
826 * Convert local time to GMT.
827 *
828 * @param tv Time to convert.
829 *
830 * @return zero if successfull.
831 */
832PJ_DECL(pj_status_t) pj_time_local_to_gmt(pj_time_val *tv);
833
834/**
835 * Convert GMT to local time.
836 *
837 * @param tv Time to convert.
838 *
839 * @return zero if successfull.
840 */
841PJ_DECL(pj_status_t) pj_time_gmt_to_local(pj_time_val *tv);
842
843/**
844 * @}
845 */
846
Benny Prijono92ac4472006-07-22 13:42:56 +0000847/* **************************************************************************/
Benny Prijono9033e312005-11-21 02:08:39 +0000848#if defined(PJ_TERM_HAS_COLOR) && PJ_TERM_HAS_COLOR != 0
849
850/**
851 * @defgroup PJ_TERM Terminal
852 * @ingroup PJ_OS
853 * @{
854 */
855
856/**
857 * Set current terminal color.
858 *
859 * @param color The RGB color.
860 *
861 * @return zero on success.
862 */
863PJ_DECL(pj_status_t) pj_term_set_color(pj_color_t color);
864
865/**
866 * Get current terminal foreground color.
867 *
868 * @return RGB color.
869 */
870PJ_DECL(pj_color_t) pj_term_get_color(void);
871
872/**
873 * @}
874 */
875
876#endif /* PJ_TERM_HAS_COLOR */
877
Benny Prijono92ac4472006-07-22 13:42:56 +0000878/* **************************************************************************/
Benny Prijono9033e312005-11-21 02:08:39 +0000879/**
880 * @defgroup PJ_TIMESTAMP High Resolution Timestamp
881 * @ingroup PJ_OS
882 * @{
883 *
884 * PJLIB provides <b>High Resolution Timestamp</b> API to access highest
885 * resolution timestamp value provided by the platform. The API is usefull
886 * to measure precise elapsed time, and can be used in applications such
887 * as profiling.
888 *
889 * The timestamp value is represented in cycles, and can be related to
890 * normal time (in seconds or sub-seconds) using various functions provided.
891 *
892 * \section pj_timestamp_examples_sec Examples
893 *
894 * For examples, please see:
895 * - \ref page_pjlib_sleep_test
896 * - \ref page_pjlib_timestamp_test
897 */
898
899/*
900 * High resolution timer.
901 */
902#if defined(PJ_HAS_HIGH_RES_TIMER) && PJ_HAS_HIGH_RES_TIMER != 0
903
904/**
Benny Prijono9033e312005-11-21 02:08:39 +0000905 * Acquire high resolution timer value. The time value are stored
906 * in cycles.
907 *
908 * @param ts High resolution timer value.
909 * @return PJ_SUCCESS or the appropriate error code.
910 *
911 * @see pj_get_timestamp_freq().
912 */
913PJ_DECL(pj_status_t) pj_get_timestamp(pj_timestamp *ts);
914
915/**
916 * Get high resolution timer frequency, in cycles per second.
917 *
918 * @param freq Timer frequency, in cycles per second.
919 * @return PJ_SUCCESS or the appropriate error code.
920 */
921PJ_DECL(pj_status_t) pj_get_timestamp_freq(pj_timestamp *freq);
922
923/**
Benny Prijonoc357d642007-01-20 05:14:24 +0000924 * Set timestamp from 32bit values.
925 * @param t The timestamp to be set.
926 * @param hi The high 32bit part.
927 * @param lo The low 32bit part.
928 */
929PJ_INLINE(void) pj_set_timestamp32(pj_timestamp *t, pj_uint32_t hi,
930 pj_uint32_t lo)
931{
932 t->u32.hi = hi;
933 t->u32.lo = lo;
934}
935
936/**
Benny Prijono9033e312005-11-21 02:08:39 +0000937 * Add timestamp t2 to t1.
938 * @param t1 t1.
939 * @param t2 t2.
940 */
941PJ_INLINE(void) pj_add_timestamp(pj_timestamp *t1, const pj_timestamp *t2)
942{
943#if PJ_HAS_INT64
944 t1->u64 += t2->u64;
945#else
946 pj_uint32_t old = t1->u32.lo;
947 t1->u32.hi += t2->u32.hi;
948 t1->u32.lo += t2->u32.lo;
949 if (t1->u32.lo < old)
950 ++t1->u32.hi;
951#endif
952}
953
954/**
Benny Prijonoc357d642007-01-20 05:14:24 +0000955 * Add timestamp t2 to t1.
956 * @param t1 t1.
957 * @param t2 t2.
958 */
959PJ_INLINE(void) pj_add_timestamp32(pj_timestamp *t1, pj_uint32_t t2)
960{
961#if PJ_HAS_INT64
962 t1->u64 += t2;
963#else
964 pj_uint32_t old = t1->u32.lo;
965 t1->u32.lo += t2;
966 if (t1->u32.lo < old)
967 ++t1->u32.hi;
968#endif
969}
970
971/**
Benny Prijono9033e312005-11-21 02:08:39 +0000972 * Substract timestamp t2 from t1.
973 * @param t1 t1.
974 * @param t2 t2.
975 */
976PJ_INLINE(void) pj_sub_timestamp(pj_timestamp *t1, const pj_timestamp *t2)
977{
978#if PJ_HAS_INT64
979 t1->u64 -= t2->u64;
980#else
981 t1->u32.hi -= t2->u32.hi;
982 if (t1->u32.lo >= t2->u32.lo)
983 t1->u32.lo -= t2->u32.lo;
984 else {
985 t1->u32.lo -= t2->u32.lo;
986 --t1->u32.hi;
987 }
988#endif
989}
990
991/**
Benny Prijonoc357d642007-01-20 05:14:24 +0000992 * Substract timestamp t2 from t1.
993 * @param t1 t1.
994 * @param t2 t2.
995 */
996PJ_INLINE(void) pj_sub_timestamp32(pj_timestamp *t1, pj_uint32_t t2)
997{
998#if PJ_HAS_INT64
999 t1->u64 -= t2;
1000#else
1001 if (t1->u32.lo >= t2)
1002 t1->u32.lo -= t2;
1003 else {
1004 t1->u32.lo -= t2;
1005 --t1->u32.hi;
1006 }
1007#endif
1008}
1009
1010/**
1011 * Get the timestamp difference between t2 and t1 (that is t2 minus t1),
1012 * and return a 32bit signed integer difference.
1013 */
1014PJ_INLINE(pj_int32_t) pj_timestamp_diff32(const pj_timestamp *t1,
1015 const pj_timestamp *t2)
1016{
1017 /* Be careful with the signess (I think!) */
1018#if PJ_HAS_INT64
1019 pj_int64_t diff = t2->u64 - t1->u64;
1020 return (pj_int32_t) diff;
1021#else
1022 pj_int32 diff = t2->u32.lo - t1->u32.lo;
1023 return diff;
1024#endif
1025}
1026
1027
1028/**
Benny Prijono9033e312005-11-21 02:08:39 +00001029 * Calculate the elapsed time, and store it in pj_time_val.
1030 * This function calculates the elapsed time using highest precision
1031 * calculation that is available for current platform, considering
1032 * whether floating point or 64-bit precision arithmetic is available.
1033 * For maximum portability, application should prefer to use this function
1034 * rather than calculating the elapsed time by itself.
1035 *
1036 * @param start The starting timestamp.
1037 * @param stop The end timestamp.
1038 *
1039 * @return Elapsed time as #pj_time_val.
1040 *
1041 * @see pj_elapsed_usec(), pj_elapsed_cycle(), pj_elapsed_nanosec()
1042 */
1043PJ_DECL(pj_time_val) pj_elapsed_time( const pj_timestamp *start,
1044 const pj_timestamp *stop );
1045
1046/**
Benny Prijono99683ae2005-11-21 16:59:47 +00001047 * Calculate the elapsed time as 32-bit miliseconds.
1048 * This function calculates the elapsed time using highest precision
1049 * calculation that is available for current platform, considering
1050 * whether floating point or 64-bit precision arithmetic is available.
1051 * For maximum portability, application should prefer to use this function
1052 * rather than calculating the elapsed time by itself.
1053 *
1054 * @param start The starting timestamp.
1055 * @param stop The end timestamp.
1056 *
1057 * @return Elapsed time in milisecond.
1058 *
1059 * @see pj_elapsed_time(), pj_elapsed_cycle(), pj_elapsed_nanosec()
1060 */
1061PJ_DECL(pj_uint32_t) pj_elapsed_msec( const pj_timestamp *start,
1062 const pj_timestamp *stop );
1063
1064/**
Benny Prijono9033e312005-11-21 02:08:39 +00001065 * Calculate the elapsed time in 32-bit microseconds.
1066 * This function calculates the elapsed time using highest precision
1067 * calculation that is available for current platform, considering
1068 * whether floating point or 64-bit precision arithmetic is available.
1069 * For maximum portability, application should prefer to use this function
1070 * rather than calculating the elapsed time by itself.
1071 *
1072 * @param start The starting timestamp.
1073 * @param stop The end timestamp.
1074 *
1075 * @return Elapsed time in microsecond.
1076 *
1077 * @see pj_elapsed_time(), pj_elapsed_cycle(), pj_elapsed_nanosec()
1078 */
1079PJ_DECL(pj_uint32_t) pj_elapsed_usec( const pj_timestamp *start,
1080 const pj_timestamp *stop );
1081
1082/**
1083 * Calculate the elapsed time in 32-bit nanoseconds.
1084 * This function calculates the elapsed time using highest precision
1085 * calculation that is available for current platform, considering
1086 * whether floating point or 64-bit precision arithmetic is available.
1087 * For maximum portability, application should prefer to use this function
1088 * rather than calculating the elapsed time by itself.
1089 *
1090 * @param start The starting timestamp.
1091 * @param stop The end timestamp.
1092 *
1093 * @return Elapsed time in nanoseconds.
1094 *
1095 * @see pj_elapsed_time(), pj_elapsed_cycle(), pj_elapsed_usec()
1096 */
1097PJ_DECL(pj_uint32_t) pj_elapsed_nanosec( const pj_timestamp *start,
1098 const pj_timestamp *stop );
1099
1100/**
1101 * Calculate the elapsed time in 32-bit cycles.
1102 * This function calculates the elapsed time using highest precision
1103 * calculation that is available for current platform, considering
1104 * whether floating point or 64-bit precision arithmetic is available.
1105 * For maximum portability, application should prefer to use this function
1106 * rather than calculating the elapsed time by itself.
1107 *
1108 * @param start The starting timestamp.
1109 * @param stop The end timestamp.
1110 *
1111 * @return Elapsed time in cycles.
1112 *
1113 * @see pj_elapsed_usec(), pj_elapsed_time(), pj_elapsed_nanosec()
1114 */
1115PJ_DECL(pj_uint32_t) pj_elapsed_cycle( const pj_timestamp *start,
1116 const pj_timestamp *stop );
1117
1118
1119#endif /* PJ_HAS_HIGH_RES_TIMER */
1120
1121/** @} */
1122
1123
Benny Prijono92ac4472006-07-22 13:42:56 +00001124/* **************************************************************************/
Benny Prijono9033e312005-11-21 02:08:39 +00001125/**
1126 * Internal PJLIB function to initialize the threading subsystem.
1127 * @return PJ_SUCCESS or the appropriate error code.
1128 */
1129pj_status_t pj_thread_init(void);
1130
1131
1132PJ_END_DECL
1133
1134#endif /* __PJ_OS_H__ */
1135