blob: 2a57ab878b558b3daff1ab78436754c3caf3ff82 [file] [log] [blame]
Benny Prijono9033e312005-11-21 02:08:39 +00001/* $Id$ */
2/*
3 * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
4 *
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
36///////////////////////////////////////////////////////////////////////////////
37/**
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)
70# define PJ_THREAD_DESC_SIZE (16)
71#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/**
133 * Get thread name.
134 *
135 * @param thread The thread handle.
136 *
137 * @return Thread name as null terminated string.
138 */
139PJ_DECL(const char*) pj_thread_get_name(pj_thread_t *thread);
140
141/**
142 * Resume a suspended thread.
143 *
144 * @param thread The thread handle.
145 *
146 * @return zero on success.
147 */
148PJ_DECL(pj_status_t) pj_thread_resume(pj_thread_t *thread);
149
150/**
151 * Get the current thread.
152 *
153 * @return Thread handle of current thread.
154 */
155PJ_DECL(pj_thread_t*) pj_thread_this(void);
156
157/**
Benny Prijono42c5b9e2006-05-10 19:24:40 +0000158 * Join thread, and block the caller thread until the specified thread exits.
159 * If the specified thread has already been dead, or it does not exist,
160 * the function will return immediately with successfull status.
Benny Prijono9033e312005-11-21 02:08:39 +0000161 *
162 * @param thread The thread handle.
163 *
Benny Prijono42c5b9e2006-05-10 19:24:40 +0000164 * @return PJ_SUCCESS on success.
Benny Prijono9033e312005-11-21 02:08:39 +0000165 */
166PJ_DECL(pj_status_t) pj_thread_join(pj_thread_t *thread);
167
168
169/**
170 * Destroy thread and release resources allocated for the thread.
171 * However, the memory allocated for the pj_thread_t itself will only be released
172 * when the pool used to create the thread is destroyed.
173 *
174 * @param thread The thread handle.
175 *
176 * @return zero on success.
177 */
178PJ_DECL(pj_status_t) pj_thread_destroy(pj_thread_t *thread);
179
180
181/**
182 * Put the current thread to sleep for the specified miliseconds.
183 *
184 * @param msec Miliseconds delay.
185 *
186 * @return zero if successfull.
187 */
188PJ_DECL(pj_status_t) pj_thread_sleep(unsigned msec);
189
190/**
191 * @def PJ_CHECK_STACK()
192 * PJ_CHECK_STACK() macro is used to check the sanity of the stack.
193 * The OS implementation may check that no stack overflow occurs, and
194 * it also may collect statistic about stack usage.
195 */
196#if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK!=0
197
198# define PJ_CHECK_STACK() pj_thread_check_stack(__FILE__, __LINE__)
199
200/** @internal
201 * The implementation of stack checking.
202 */
203PJ_DECL(void) pj_thread_check_stack(const char *file, int line);
204
205/** @internal
206 * Get maximum stack usage statistic.
207 */
208PJ_DECL(pj_uint32_t) pj_thread_get_stack_max_usage(pj_thread_t *thread);
209
210/** @internal
211 * Dump thread stack status.
212 */
213PJ_DECL(pj_status_t) pj_thread_get_stack_info(pj_thread_t *thread,
214 const char **file,
215 int *line);
216#else
217
218# define PJ_CHECK_STACK()
219/** pj_thread_get_stack_max_usage() for the thread */
220# define pj_thread_get_stack_max_usage(thread) 0
221/** pj_thread_get_stack_info() for the thread */
222# define pj_thread_get_stack_info(thread,f,l) (*(f)="",*(l)=0)
223#endif /* PJ_OS_HAS_CHECK_STACK */
224
225/**
226 * @}
227 */
228
229///////////////////////////////////////////////////////////////////////////////
230/**
231 * @defgroup PJ_TLS Thread Local Storage.
232 * @ingroup PJ_OS
233 * @{
234 */
235
236/**
237 * Allocate thread local storage index. The initial value of the variable at
238 * the index is zero.
239 *
240 * @param index Pointer to hold the return value.
241 * @return PJ_SUCCESS on success, or the error code.
242 */
243PJ_DECL(pj_status_t) pj_thread_local_alloc(long *index);
244
245/**
246 * Deallocate thread local variable.
247 *
248 * @param index The variable index.
249 */
250PJ_DECL(void) pj_thread_local_free(long index);
251
252/**
253 * Set the value of thread local variable.
254 *
255 * @param index The index of the variable.
256 * @param value The value.
257 */
258PJ_DECL(pj_status_t) pj_thread_local_set(long index, void *value);
259
260/**
261 * Get the value of thread local variable.
262 *
263 * @param index The index of the variable.
264 * @return The value.
265 */
266PJ_DECL(void*) pj_thread_local_get(long index);
267
268
269/**
270 * @}
271 */
272
273
274///////////////////////////////////////////////////////////////////////////////
275/**
276 * @defgroup PJ_ATOMIC Atomic Variables
277 * @ingroup PJ_OS
278 * @{
279 *
280 * This module provides API to manipulate atomic variables.
281 *
282 * \section pj_atomic_examples_sec Examples
283 *
284 * For some example codes, please see:
285 * - @ref page_pjlib_atomic_test
286 */
287
288
289/**
290 * Create atomic variable.
291 *
292 * @param pool The pool.
293 * @param initial The initial value of the atomic variable.
294 * @param atomic Pointer to hold the atomic variable upon return.
295 *
296 * @return PJ_SUCCESS on success, or the error code.
297 */
298PJ_DECL(pj_status_t) pj_atomic_create( pj_pool_t *pool,
299 pj_atomic_value_t initial,
300 pj_atomic_t **atomic );
301
302/**
303 * Destroy atomic variable.
304 *
305 * @param atomic_var the atomic variable.
306 *
307 * @return PJ_SUCCESS if success.
308 */
309PJ_DECL(pj_status_t) pj_atomic_destroy( pj_atomic_t *atomic_var );
310
311/**
312 * Set the value of an atomic type, and return the previous value.
313 *
314 * @param atomic_var the atomic variable.
315 * @param value value to be set to the variable.
316 */
317PJ_DECL(void) pj_atomic_set( pj_atomic_t *atomic_var,
318 pj_atomic_value_t value);
319
320/**
321 * Get the value of an atomic type.
322 *
323 * @param atomic_var the atomic variable.
324 *
325 * @return the value of the atomic variable.
326 */
327PJ_DECL(pj_atomic_value_t) pj_atomic_get(pj_atomic_t *atomic_var);
328
329/**
330 * Increment the value of an atomic type.
331 *
332 * @param atomic_var the atomic variable.
333 */
334PJ_DECL(void) pj_atomic_inc(pj_atomic_t *atomic_var);
335
336/**
337 * Increment the value of an atomic type and get the result.
338 *
339 * @param atomic_var the atomic variable.
340 *
341 * @return The incremented value.
342 */
343PJ_DECL(pj_atomic_value_t) pj_atomic_inc_and_get(pj_atomic_t *atomic_var);
344
345/**
346 * Decrement the value of an atomic type.
347 *
348 * @param atomic_var the atomic variable.
349 */
350PJ_DECL(void) pj_atomic_dec(pj_atomic_t *atomic_var);
351
352/**
353 * Decrement the value of an atomic type and get the result.
354 *
355 * @param atomic_var the atomic variable.
356 *
357 * @return The decremented value.
358 */
359PJ_DECL(pj_atomic_value_t) pj_atomic_dec_and_get(pj_atomic_t *atomic_var);
360
361/**
362 * Add a value to an atomic type.
363 *
364 * @param atomic_var The atomic variable.
365 * @param value Value to be added.
366 */
367PJ_DECL(void) pj_atomic_add( pj_atomic_t *atomic_var,
368 pj_atomic_value_t value);
369
370/**
371 * Add a value to an atomic type and get the result.
372 *
373 * @param atomic_var The atomic variable.
374 * @param value Value to be added.
375 *
376 * @return The result after the addition.
377 */
378PJ_DECL(pj_atomic_value_t) pj_atomic_add_and_get( pj_atomic_t *atomic_var,
379 pj_atomic_value_t value);
380
381/**
382 * @}
383 */
384
385///////////////////////////////////////////////////////////////////////////////
386/**
387 * @defgroup PJ_MUTEX Mutexes.
388 * @ingroup PJ_OS
389 * @{
390 *
391 * Mutex manipulation. Alternatively, application can use higher abstraction
392 * for lock objects, which provides uniform API for all kinds of lock
393 * mechanisms, including mutex. See @ref PJ_LOCK for more information.
394 */
395
396/**
397 * Mutex types:
398 * - PJ_MUTEX_DEFAULT: default mutex type, which is system dependent.
399 * - PJ_MUTEX_SIMPLE: non-recursive mutex.
400 * - PJ_MUTEX_RECURSIVE: recursive mutex.
401 */
402typedef enum pj_mutex_type_e
403{
404 PJ_MUTEX_DEFAULT,
405 PJ_MUTEX_SIMPLE,
406 PJ_MUTEX_RECURSE,
407} pj_mutex_type_e;
408
409
410/**
411 * Create mutex of the specified type.
412 *
413 * @param pool The pool.
414 * @param name Name to be associated with the mutex (for debugging).
415 * @param type The type of the mutex, of type #pj_mutex_type_e.
416 * @param mutex Pointer to hold the returned mutex instance.
417 *
418 * @return PJ_SUCCESS on success, or the error code.
419 */
420PJ_DECL(pj_status_t) pj_mutex_create(pj_pool_t *pool,
421 const char *name,
422 int type,
423 pj_mutex_t **mutex);
424
425/**
426 * Create simple, non-recursive mutex.
427 * This function is a simple wrapper for #pj_mutex_create to create
428 * non-recursive mutex.
429 *
430 * @param pool The pool.
431 * @param name Mutex name.
432 * @param mutex Pointer to hold the returned mutex instance.
433 *
434 * @return PJ_SUCCESS on success, or the error code.
435 */
436PJ_DECL(pj_status_t) pj_mutex_create_simple( pj_pool_t *pool, const char *name,
437 pj_mutex_t **mutex );
438
439/**
440 * Create recursive mutex.
441 * This function is a simple wrapper for #pj_mutex_create to create
442 * recursive mutex.
443 *
444 * @param pool The pool.
445 * @param name Mutex name.
446 * @param mutex Pointer to hold the returned mutex instance.
447 *
448 * @return PJ_SUCCESS on success, or the error code.
449 */
450PJ_DECL(pj_status_t) pj_mutex_create_recursive( pj_pool_t *pool,
451 const char *name,
452 pj_mutex_t **mutex );
453
454/**
455 * Acquire mutex lock.
456 *
457 * @param mutex The mutex.
458 * @return PJ_SUCCESS on success, or the error code.
459 */
460PJ_DECL(pj_status_t) pj_mutex_lock(pj_mutex_t *mutex);
461
462/**
463 * Release 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_unlock(pj_mutex_t *mutex);
469
470/**
471 * Try to acquire mutex lock.
472 *
473 * @param mutex The mutex.
474 * @return PJ_SUCCESS on success, or the error code if the
475 * lock couldn't be acquired.
476 */
477PJ_DECL(pj_status_t) pj_mutex_trylock(pj_mutex_t *mutex);
478
479/**
480 * Destroy mutex.
481 *
482 * @param mutex Te mutex.
483 * @return PJ_SUCCESS on success, or the error code.
484 */
485PJ_DECL(pj_status_t) pj_mutex_destroy(pj_mutex_t *mutex);
486
487/**
488 * Determine whether calling thread is owning the mutex (only available when
489 * PJ_DEBUG is set).
490 * @param mutex The mutex.
491 * @return Non-zero if yes.
492 */
493#if defined(PJ_DEBUG) && PJ_DEBUG != 0
494 PJ_DECL(pj_bool_t) pj_mutex_is_locked(pj_mutex_t *mutex);
495#else
496# define pj_mutex_is_locked(mutex) 1
497#endif
498
499/**
500 * @}
501 */
502
503///////////////////////////////////////////////////////////////////////////////
504/**
Benny Prijono0ca04b62005-12-30 23:50:15 +0000505 * @defgroup PJ_RW_MUTEX Reader/Writer Mutex
506 * @ingroup PJ_OS
507 * @{
508 * Reader/writer mutex is a classic synchronization object where multiple
509 * readers can acquire the mutex, but only a single writer can acquire the
510 * mutex.
511 */
Benny Prijono294c2532006-06-16 16:52:51 +0000512
513/**
514 * Opaque declaration for reader/writer mutex.
515 * Reader/writer mutex is a classic synchronization object where multiple
516 * readers can acquire the mutex, but only a single writer can acquire the
517 * mutex.
518 */
Benny Prijono0ca04b62005-12-30 23:50:15 +0000519typedef struct pj_rwmutex_t pj_rwmutex_t;
520
521/**
522 * Create reader/writer mutex.
523 *
524 * @param pool Pool to allocate memory for the mutex.
525 * @param name Name to be assigned to the mutex.
526 * @param mutex Pointer to receive the newly created mutex.
527 *
528 * @return PJ_SUCCESS on success, or the error code.
529 */
530PJ_DECL(pj_status_t) pj_rwmutex_create(pj_pool_t *pool, const char *name,
531 pj_rwmutex_t **mutex);
532
533/**
534 * Lock the mutex for reading.
535 *
536 * @param mutex The mutex.
537 * @return PJ_SUCCESS on success, or the error code.
538 */
539PJ_DECL(pj_status_t) pj_rwmutex_lock_read(pj_rwmutex_t *mutex);
540
541/**
542 * Lock the mutex for writing.
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_write(pj_rwmutex_t *mutex);
548
549/**
550 * Release read lock.
551 *
552 * @param mutex The mutex.
553 * @return PJ_SUCCESS on success, or the error code.
554 */
555PJ_DECL(pj_status_t) pj_rwmutex_unlock_read(pj_rwmutex_t *mutex);
556
557/**
558 * Release write 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_write(pj_rwmutex_t *mutex);
564
565/**
566 * Destroy reader/writer mutex.
567 *
568 * @param mutex The mutex.
569 * @return PJ_SUCCESS on success, or the error code.
570 */
571PJ_DECL(pj_status_t) pj_rwmutex_destroy(pj_rwmutex_t *mutex);
572
573
574/**
575 * @}
576 */
577
578
579///////////////////////////////////////////////////////////////////////////////
580/**
Benny Prijono9033e312005-11-21 02:08:39 +0000581 * @defgroup PJ_CRIT_SEC Critical sections.
582 * @ingroup PJ_OS
583 * @{
584 * Critical section protection can be used to protect regions where:
585 * - mutual exclusion protection is needed.
586 * - it's rather too expensive to create a mutex.
587 * - the time spent in the region is very very brief.
588 *
589 * Critical section is a global object, and it prevents any threads from
590 * entering any regions that are protected by critical section once a thread
591 * is already in the section.
592 *
593 * Critial section is \a not recursive!
594 *
595 * Application <b>MUST NOT</b> call any functions that may cause current
596 * thread to block (such as allocating memory, performing I/O, locking mutex,
597 * etc.) while holding the critical section.
598 */
599/**
600 * Enter critical section.
601 */
602PJ_DECL(void) pj_enter_critical_section(void);
603
604/**
605 * Leave critical section.
606 */
607PJ_DECL(void) pj_leave_critical_section(void);
608
609/**
610 * @}
611 */
612
613///////////////////////////////////////////////////////////////////////////////
614#if defined(PJ_HAS_SEMAPHORE) && PJ_HAS_SEMAPHORE != 0
615/**
616 * @defgroup PJ_SEM Semaphores.
617 * @ingroup PJ_OS
618 * @{
619 *
620 * This module provides abstraction for semaphores, where available.
621 */
622
623/**
624 * Create semaphore.
625 *
626 * @param pool The pool.
627 * @param name Name to be assigned to the semaphore (for logging purpose)
628 * @param initial The initial count of the semaphore.
629 * @param max The maximum count of the semaphore.
630 * @param sem Pointer to hold the semaphore created.
631 *
632 * @return PJ_SUCCESS on success, or the error code.
633 */
634PJ_DECL(pj_status_t) pj_sem_create( pj_pool_t *pool,
635 const char *name,
636 unsigned initial,
637 unsigned max,
638 pj_sem_t **sem);
639
640/**
641 * Wait for semaphore.
642 *
643 * @param sem The semaphore.
644 *
645 * @return PJ_SUCCESS on success, or the error code.
646 */
647PJ_DECL(pj_status_t) pj_sem_wait(pj_sem_t *sem);
648
649/**
650 * Try wait for semaphore.
651 *
652 * @param sem The semaphore.
653 *
654 * @return PJ_SUCCESS on success, or the error code.
655 */
656PJ_DECL(pj_status_t) pj_sem_trywait(pj_sem_t *sem);
657
658/**
659 * Release semaphore.
660 *
661 * @param sem The semaphore.
662 *
663 * @return PJ_SUCCESS on success, or the error code.
664 */
665PJ_DECL(pj_status_t) pj_sem_post(pj_sem_t *sem);
666
667/**
668 * Destroy semaphore.
669 *
670 * @param sem The semaphore.
671 *
672 * @return PJ_SUCCESS on success, or the error code.
673 */
674PJ_DECL(pj_status_t) pj_sem_destroy(pj_sem_t *sem);
675
676/**
677 * @}
678 */
679#endif /* PJ_HAS_SEMAPHORE */
680
681
682///////////////////////////////////////////////////////////////////////////////
683#if defined(PJ_HAS_EVENT_OBJ) && PJ_HAS_EVENT_OBJ != 0
684/**
685 * @defgroup PJ_EVENT Event Object.
686 * @ingroup PJ_OS
687 * @{
688 *
689 * This module provides abstraction to event object (e.g. Win32 Event) where
690 * available. Event objects can be used for synchronization among threads.
691 */
692
693/**
694 * Create event object.
695 *
696 * @param pool The pool.
697 * @param name The name of the event object (for logging purpose).
698 * @param manual_reset Specify whether the event is manual-reset
699 * @param initial Specify the initial state of the event object.
700 * @param event Pointer to hold the returned event object.
701 *
702 * @return event handle, or NULL if failed.
703 */
704PJ_DECL(pj_status_t) pj_event_create(pj_pool_t *pool, const char *name,
705 pj_bool_t manual_reset, pj_bool_t initial,
706 pj_event_t **event);
707
708/**
709 * Wait for event to be signaled.
710 *
711 * @param event The event object.
712 *
713 * @return zero if successfull.
714 */
715PJ_DECL(pj_status_t) pj_event_wait(pj_event_t *event);
716
717/**
718 * Try wait for event object to be signalled.
719 *
720 * @param event The event object.
721 *
722 * @return zero if successfull.
723 */
724PJ_DECL(pj_status_t) pj_event_trywait(pj_event_t *event);
725
726/**
727 * Set the event object state to signaled. For auto-reset event, this
728 * will only release the first thread that are waiting on the event. For
729 * manual reset event, the state remains signaled until the event is reset.
730 * If there is no thread waiting on the event, the event object state
731 * remains signaled.
732 *
733 * @param event The event object.
734 *
735 * @return zero if successfull.
736 */
737PJ_DECL(pj_status_t) pj_event_set(pj_event_t *event);
738
739/**
740 * Set the event object to signaled state to release appropriate number of
741 * waiting threads and then reset the event object to non-signaled. For
742 * manual-reset event, this function will release all waiting threads. For
743 * auto-reset event, this function will only release one waiting thread.
744 *
745 * @param event The event object.
746 *
747 * @return zero if successfull.
748 */
749PJ_DECL(pj_status_t) pj_event_pulse(pj_event_t *event);
750
751/**
752 * Set the event object state to non-signaled.
753 *
754 * @param event The event object.
755 *
756 * @return zero if successfull.
757 */
758PJ_DECL(pj_status_t) pj_event_reset(pj_event_t *event);
759
760/**
761 * Destroy the event object.
762 *
763 * @param event The event object.
764 *
765 * @return zero if successfull.
766 */
767PJ_DECL(pj_status_t) pj_event_destroy(pj_event_t *event);
768
769/**
770 * @}
771 */
772#endif /* PJ_HAS_EVENT_OBJ */
773
774///////////////////////////////////////////////////////////////////////////////
775/**
776 * @addtogroup PJ_TIME Time Data Type and Manipulation.
777 * @ingroup PJ_OS
778 * @{
779 * This module provides API for manipulating time.
780 *
781 * \section pj_time_examples_sec Examples
782 *
783 * For examples, please see:
784 * - \ref page_pjlib_sleep_test
785 */
786
787/**
788 * Get current time of day in local representation.
789 *
790 * @param tv Variable to store the result.
791 *
792 * @return zero if successfull.
793 */
794PJ_DECL(pj_status_t) pj_gettimeofday(pj_time_val *tv);
795
796
797/**
798 * Parse time value into date/time representation.
799 *
800 * @param tv The time.
801 * @param pt Variable to store the date time result.
802 *
803 * @return zero if successfull.
804 */
805PJ_DECL(pj_status_t) pj_time_decode(const pj_time_val *tv, pj_parsed_time *pt);
806
807/**
808 * Encode date/time to time value.
809 *
810 * @param pt The date/time.
811 * @param tv Variable to store time value result.
812 *
813 * @return zero if successfull.
814 */
815PJ_DECL(pj_status_t) pj_time_encode(const pj_parsed_time *pt, pj_time_val *tv);
816
817/**
818 * Convert local time to GMT.
819 *
820 * @param tv Time to convert.
821 *
822 * @return zero if successfull.
823 */
824PJ_DECL(pj_status_t) pj_time_local_to_gmt(pj_time_val *tv);
825
826/**
827 * Convert GMT to local time.
828 *
829 * @param tv Time to convert.
830 *
831 * @return zero if successfull.
832 */
833PJ_DECL(pj_status_t) pj_time_gmt_to_local(pj_time_val *tv);
834
835/**
836 * @}
837 */
838
839///////////////////////////////////////////////////////////////////////////////
840#if defined(PJ_TERM_HAS_COLOR) && PJ_TERM_HAS_COLOR != 0
841
842/**
843 * @defgroup PJ_TERM Terminal
844 * @ingroup PJ_OS
845 * @{
846 */
847
848/**
849 * Set current terminal color.
850 *
851 * @param color The RGB color.
852 *
853 * @return zero on success.
854 */
855PJ_DECL(pj_status_t) pj_term_set_color(pj_color_t color);
856
857/**
858 * Get current terminal foreground color.
859 *
860 * @return RGB color.
861 */
862PJ_DECL(pj_color_t) pj_term_get_color(void);
863
864/**
865 * @}
866 */
867
868#endif /* PJ_TERM_HAS_COLOR */
869
870///////////////////////////////////////////////////////////////////////////////
871/**
872 * @defgroup PJ_TIMESTAMP High Resolution Timestamp
873 * @ingroup PJ_OS
874 * @{
875 *
876 * PJLIB provides <b>High Resolution Timestamp</b> API to access highest
877 * resolution timestamp value provided by the platform. The API is usefull
878 * to measure precise elapsed time, and can be used in applications such
879 * as profiling.
880 *
881 * The timestamp value is represented in cycles, and can be related to
882 * normal time (in seconds or sub-seconds) using various functions provided.
883 *
884 * \section pj_timestamp_examples_sec Examples
885 *
886 * For examples, please see:
887 * - \ref page_pjlib_sleep_test
888 * - \ref page_pjlib_timestamp_test
889 */
890
891/*
892 * High resolution timer.
893 */
894#if defined(PJ_HAS_HIGH_RES_TIMER) && PJ_HAS_HIGH_RES_TIMER != 0
895
896/**
Benny Prijono9033e312005-11-21 02:08:39 +0000897 * Acquire high resolution timer value. The time value are stored
898 * in cycles.
899 *
900 * @param ts High resolution timer value.
901 * @return PJ_SUCCESS or the appropriate error code.
902 *
903 * @see pj_get_timestamp_freq().
904 */
905PJ_DECL(pj_status_t) pj_get_timestamp(pj_timestamp *ts);
906
907/**
908 * Get high resolution timer frequency, in cycles per second.
909 *
910 * @param freq Timer frequency, in cycles per second.
911 * @return PJ_SUCCESS or the appropriate error code.
912 */
913PJ_DECL(pj_status_t) pj_get_timestamp_freq(pj_timestamp *freq);
914
915/**
916 * Add timestamp t2 to t1.
917 * @param t1 t1.
918 * @param t2 t2.
919 */
920PJ_INLINE(void) pj_add_timestamp(pj_timestamp *t1, const pj_timestamp *t2)
921{
922#if PJ_HAS_INT64
923 t1->u64 += t2->u64;
924#else
925 pj_uint32_t old = t1->u32.lo;
926 t1->u32.hi += t2->u32.hi;
927 t1->u32.lo += t2->u32.lo;
928 if (t1->u32.lo < old)
929 ++t1->u32.hi;
930#endif
931}
932
933/**
934 * Substract timestamp t2 from t1.
935 * @param t1 t1.
936 * @param t2 t2.
937 */
938PJ_INLINE(void) pj_sub_timestamp(pj_timestamp *t1, const pj_timestamp *t2)
939{
940#if PJ_HAS_INT64
941 t1->u64 -= t2->u64;
942#else
943 t1->u32.hi -= t2->u32.hi;
944 if (t1->u32.lo >= t2->u32.lo)
945 t1->u32.lo -= t2->u32.lo;
946 else {
947 t1->u32.lo -= t2->u32.lo;
948 --t1->u32.hi;
949 }
950#endif
951}
952
953/**
954 * Calculate the elapsed time, and store it in pj_time_val.
955 * This function calculates the elapsed time using highest precision
956 * calculation that is available for current platform, considering
957 * whether floating point or 64-bit precision arithmetic is available.
958 * For maximum portability, application should prefer to use this function
959 * rather than calculating the elapsed time by itself.
960 *
961 * @param start The starting timestamp.
962 * @param stop The end timestamp.
963 *
964 * @return Elapsed time as #pj_time_val.
965 *
966 * @see pj_elapsed_usec(), pj_elapsed_cycle(), pj_elapsed_nanosec()
967 */
968PJ_DECL(pj_time_val) pj_elapsed_time( const pj_timestamp *start,
969 const pj_timestamp *stop );
970
971/**
Benny Prijono99683ae2005-11-21 16:59:47 +0000972 * Calculate the elapsed time as 32-bit miliseconds.
973 * This function calculates the elapsed time using highest precision
974 * calculation that is available for current platform, considering
975 * whether floating point or 64-bit precision arithmetic is available.
976 * For maximum portability, application should prefer to use this function
977 * rather than calculating the elapsed time by itself.
978 *
979 * @param start The starting timestamp.
980 * @param stop The end timestamp.
981 *
982 * @return Elapsed time in milisecond.
983 *
984 * @see pj_elapsed_time(), pj_elapsed_cycle(), pj_elapsed_nanosec()
985 */
986PJ_DECL(pj_uint32_t) pj_elapsed_msec( const pj_timestamp *start,
987 const pj_timestamp *stop );
988
989/**
Benny Prijono9033e312005-11-21 02:08:39 +0000990 * Calculate the elapsed time in 32-bit microseconds.
991 * This function calculates the elapsed time using highest precision
992 * calculation that is available for current platform, considering
993 * whether floating point or 64-bit precision arithmetic is available.
994 * For maximum portability, application should prefer to use this function
995 * rather than calculating the elapsed time by itself.
996 *
997 * @param start The starting timestamp.
998 * @param stop The end timestamp.
999 *
1000 * @return Elapsed time in microsecond.
1001 *
1002 * @see pj_elapsed_time(), pj_elapsed_cycle(), pj_elapsed_nanosec()
1003 */
1004PJ_DECL(pj_uint32_t) pj_elapsed_usec( const pj_timestamp *start,
1005 const pj_timestamp *stop );
1006
1007/**
1008 * Calculate the elapsed time in 32-bit nanoseconds.
1009 * This function calculates the elapsed time using highest precision
1010 * calculation that is available for current platform, considering
1011 * whether floating point or 64-bit precision arithmetic is available.
1012 * For maximum portability, application should prefer to use this function
1013 * rather than calculating the elapsed time by itself.
1014 *
1015 * @param start The starting timestamp.
1016 * @param stop The end timestamp.
1017 *
1018 * @return Elapsed time in nanoseconds.
1019 *
1020 * @see pj_elapsed_time(), pj_elapsed_cycle(), pj_elapsed_usec()
1021 */
1022PJ_DECL(pj_uint32_t) pj_elapsed_nanosec( const pj_timestamp *start,
1023 const pj_timestamp *stop );
1024
1025/**
1026 * Calculate the elapsed time in 32-bit cycles.
1027 * This function calculates the elapsed time using highest precision
1028 * calculation that is available for current platform, considering
1029 * whether floating point or 64-bit precision arithmetic is available.
1030 * For maximum portability, application should prefer to use this function
1031 * rather than calculating the elapsed time by itself.
1032 *
1033 * @param start The starting timestamp.
1034 * @param stop The end timestamp.
1035 *
1036 * @return Elapsed time in cycles.
1037 *
1038 * @see pj_elapsed_usec(), pj_elapsed_time(), pj_elapsed_nanosec()
1039 */
1040PJ_DECL(pj_uint32_t) pj_elapsed_cycle( const pj_timestamp *start,
1041 const pj_timestamp *stop );
1042
1043
1044#endif /* PJ_HAS_HIGH_RES_TIMER */
1045
1046/** @} */
1047
1048
1049///////////////////////////////////////////////////////////////////////////////
1050/**
1051 * Internal PJLIB function to initialize the threading subsystem.
1052 * @return PJ_SUCCESS or the appropriate error code.
1053 */
1054pj_status_t pj_thread_init(void);
1055
1056
1057PJ_END_DECL
1058
1059#endif /* __PJ_OS_H__ */
1060