1 /*
2  * Copyright (c) 2011 Aeroflex Gaisler
3  *
4  * BSD license:
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 
25 
26 #include <asm-leon/queue.h>
27 /*#include <sys/fsu_pthread_queue.h>*/
28 #include <asm-leon/contextswitch.h>
29 #include <asm-leon/leonbare_kernel.h>
30 #include <asm-leon/leonbare_debug.h>
31 #include <asm-leon/stack.h>
32 #include <asm-leon/leonstack.h>
33 #include <asm-leon/irq.h>
34 
35 leonbare_mutex_t
leonbare_mutex_init(leonbare_mutex_t m)36 leonbare_mutex_init (leonbare_mutex_t m)
37 {
38   m->mx_owner_cnt = 0;
39   m->mx_owner = 0;
40   LBTAILQ_INIT (&(m->mx_threads));
41 
42   LEONBARE_PROTECT_KERNEL_START ();
43   {
44     LBTAILQ_INSERT_TAIL (LEONBARE_KR_ALLM, m, mx_allm);
45   }
46   LEONBARE_PROTECT_KERNEL_END ();
47 
48 }
49 
50 int
_self__leonbare_mutex_lock(leonbare_mutex_t m,int wait)51 _self__leonbare_mutex_lock (leonbare_mutex_t m, int wait)
52 {
53   int ret = LEONBARE_MUTEX_LOCK_OK;
54   leonbare_thread_t c;
55 
56   LEONBARE_PROTECT_MUTEXSTRUCT_START (m);
57   while (1)
58     {
59       if (LEONBARE_MUTEX_OWNER_GET (m) == 0)
60 	{
61 	  LEONBARE_MUTEX_OWNER_SET (m, LEONBARE_KR_CURRENT);
62 	  LEONBARE_MUTEX_OWNER_CNT_SET (m, 0);
63 	  LBTAILQ_INSERT_TAIL (&c->th_mutex_locked, m, mx_locked);
64 	  ret = LEONBARE_MUTEX_LOCK_OK;
65 	  break;
66 	}
67       else if (m->mx_owner == LEONBARE_KR_CURRENT)
68 	{
69 	  m->mx_owner_cnt++;
70 	  ret = LEONBARE_MUTEX_LOCK_OK;
71 	  break;
72 	}
73       LBTAILQ_INSERT_TAIL (&m->mx_threads, c, th_mutex);
74       current_suspend ();
75     }
76   LEONBARE_PROTECT_MUTEXSTRUCT_END (m);
77   return ret;
78 }
79 
80 int
leonbare_mutex_unlock(leonbare_mutex_t m)81 leonbare_mutex_unlock (leonbare_mutex_t m)
82 {
83   int ret = LEONBARE_MUTEX_UNLOCK_ERROR;
84   leonbare_thread_t c, h;
85 
86   LEONBARE_PROTECT_MUTEXSTRUCT_START (m);
87   {
88     c = LEONBARE_KR_CURRENT;
89     if (m->mx_owner != c)
90       {
91 	ret = LEONBARE_MUTEX_UNLOCK_OK;
92       }
93     else if (m->mx_owner == c && m->mx_owner_cnt)
94       {
95 	m->mx_owner_cnt--;
96 	ret = LEONBARE_MUTEX_UNLOCK_OK;
97       }
98     else if ((h = LBTAILQ_FIRST (&m->mx_threads)))
99       {
100 	LBTAILQ_REMOVE (&m->mx_threads, h, th_mutex);
101 	leonbare_thread_resume (h);
102 	ret = LEONBARE_MUTEX_UNLOCK_OK;
103       }
104   }
105   LEONBARE_PROTECT_MUTEXSTRUCT_END (m);
106   return ret;
107 }
108