aboutsummaryrefslogtreecommitdiff
path: root/sem.c
blob: c34e7988f499b9b2f5a369184d37fdf75423dec1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
/************************************************************************/
/*                                                                      */
/*  File:           sem.c                                               */
/*  Description:    semaphore P and V operations.                       */
/*  Version:        1.0                                                 */
/*  Author:         Otto Mattik                                         */
/*                                                                      */
/*  (C)Copyright Otto Mattik 2014-2021.                                 */
/*                                                                      */
/*  This file is a part of 'armen' (a tiny operating system).           */
/*  'armen' is distributed under the CeCILL-V2.1 licence. For more      */
/*  details about this licence, please visit the website cecill.info    */
/*                                                                      */
/************************************************************************/

#ifdef USE_SEM

#include "core.h"

/*
 * initialize a semaphore
 *
 * input:
 *  sem         address of semaphore
 *  value       initial value for semaphore
 * output:
*/
void sem_init( sem_t* sem, uint8_t value )
{
    ((_sem_t*)sem)->lock = 0;
    ((_sem_t*)sem)->value =
    ((_sem_t*)sem)->count = value;
}

/*
 * P operation
 *
 * input:
 *  sem         address of semaphore
 * output:
 *  O if success, otherwise -1
*/
void sem_wait( sem_t* sem )
{
    while( test_and_set( sem ) != 0 ) ;
    if( ((_sem_t*)sem)->count == 0 )
    {
        ((_sem_t*)sem)->lock = 0;
        _threads[_cur_thread].sem = sem;
        wait_event( EVENT_SEM );
    }
    else
    {
        --((_sem_t*)sem)->count;
        ((_sem_t*)sem)->lock = 0;
    }
}

/*
 * V operation
 *
 * input:
 *  sem         address of semaphore
 * output:
 *  O if success, otherwise -1
*/
void sem_post( sem_t* sem )
{
    while( test_and_set( sem ) != 0 ) ;
    if( ((_sem_t*)sem)->count != ((_sem_t*)sem)->value )
    {
        ++((_sem_t*)sem)->count;
        _wakeup( EVENT_SEM, sem );
    }
    ((_sem_t*)sem)->lock = 0;
}

#endif