aboutsummaryrefslogtreecommitdiffstats
path: root/task/src/mpu/lib/task_semaphore.c
blob: 749dc9e6ca5056de93ab7b216d38cafc403e31a5 (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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/*
 * Copyright 2008 Sony Corporation of America
 *
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this Library and associated documentation files (the
 * "Library"), to deal in the Library without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Library, and to
 * permit persons to whom the Library is furnished to do so, subject to
 * the following conditions:
 *
 *  The above copyright notice and this permission notice shall be
 *  included in all copies or substantial portions of the Library.
 *
 *  If you modify the Library, you may copy and distribute your modified
 *  version of the Library in object code or as an executable provided
 *  that you also do one of the following:
 *
 *   Accompany the modified version of the Library with the complete
 *   corresponding machine-readable source code for the modified version
 *   of the Library; or,
 *
 *   Accompany the modified version of the Library with a written offer
 *   for a complete machine-readable copy of the corresponding source
 *   code of the modified version of the Library.
 *
 *
 * THE LIBRARY IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * LIBRARY OR THE USE OR OTHER DEALINGS IN THE LIBRARY.
 */

#include <stdlib.h>
#include <string.h>

#include "config.h"

#include <mars/error.h>
#include <mars/mutex.h>

#include "mars/task_types.h"
#include "mars/task_semaphore.h"

#include "task_internal_types.h"
#include "task_semaphore_internal_types.h"
#include "task_module.h"

static struct mars_task_semaphore semaphore;

int mars_task_semaphore_acquire(uint64_t semaphore_ea)
{
	struct mars_task_context *task;

	/* check function params */
	if (!semaphore_ea)
		return MARS_ERROR_NULL;
	if (semaphore_ea & MARS_TASK_SEMAPHORE_ALIGN_MASK)
		return MARS_ERROR_ALIGN;

	/* get task context */
	task = (*mars_task_module_syscalls->get_task)();

	/* make sure task context has a context save area */
	if (!task->context_save_area_ea)
		return MARS_ERROR_FORMAT;

	mars_mutex_lock_get(semaphore_ea, (struct mars_mutex *)&semaphore);

	/* check if semaphore wait limit reached */
	if (semaphore.wait_count == MARS_TASK_SEMAPHORE_WAIT_MAX) {
		mars_mutex_unlock_put(semaphore_ea,
				      (struct mars_mutex *)&semaphore);
		return MARS_ERROR_LIMIT;
	}

	if (semaphore.count <= 0) {
		/* add id to wait list */
		semaphore.wait_id[semaphore.wait_count] = task->id.workload_id;
		semaphore.wait_count++;

		mars_mutex_unlock_put(semaphore_ea,
				      (struct mars_mutex *)&semaphore);

		/* wait for signal */
		(*mars_task_module_syscalls->signal_wait)();

		return MARS_SUCCESS;
	}

	/* decrement semaphore count */
	semaphore.count--;

	mars_mutex_unlock_put(semaphore_ea, (struct mars_mutex *)&semaphore);

	return MARS_SUCCESS;
}

int mars_task_semaphore_release(uint64_t semaphore_ea)
{
	/* check function params */
	if (!semaphore_ea)
		return MARS_ERROR_NULL;
	if (semaphore_ea & MARS_TASK_SEMAPHORE_ALIGN_MASK)
		return MARS_ERROR_ALIGN;

	mars_mutex_lock_get(semaphore_ea, (struct mars_mutex *)&semaphore);

	/* increment semaphore count */
	semaphore.count++;

	/* signal those that are waiting */
	if (semaphore.count > 0 && semaphore.wait_count) {
		/* decrement semaphore count */
		semaphore.count--;

		/* signal waiting task */
		(*mars_task_module_syscalls->signal_send)
			(semaphore.wait_id[0]);

		/* flush id from wait list */
		semaphore.wait_count--;
		memmove(&semaphore.wait_id[0],
			&semaphore.wait_id[1],
			sizeof(uint16_t) * semaphore.wait_count);
	}

	mars_mutex_unlock_put(semaphore_ea, (struct mars_mutex *)&semaphore);

	return MARS_SUCCESS;
}