| Index: apps/fastboot/version.h |
| — | — | @@ -25,10 +25,10 @@ |
| 26 | 26 | #define __VERSION_H__
|
| 27 | 27 |
|
| 28 | 28 |
|
| 29 | | -#define VERSION "0.1.0"
|
| | 29 | +#define VERSION "0.1.1"
|
| 30 | 30 | #define VERSION_MAJOR 0
|
| 31 | 31 | #define VERSION_MINOR 1
|
| 32 | | -#define VERSION_PATCH 0
|
| | 32 | +#define VERSION_PATCH 1
|
| 33 | 33 | #define VERSION_SVN "$REVISION$"
|
| 34 | 34 | #define VERSION_SVN_INT $REVISIONINT$
|
| 35 | 35 |
|
| Index: emcore/trunk/version.h |
| — | — | @@ -25,10 +25,10 @@ |
| 26 | 26 | #define __VERSION_H__
|
| 27 | 27 |
|
| 28 | 28 |
|
| 29 | | -#define VERSION "0.2.0"
|
| | 29 | +#define VERSION "0.2.1"
|
| 30 | 30 | #define VERSION_MAJOR 0
|
| 31 | 31 | #define VERSION_MINOR 2
|
| 32 | | -#define VERSION_PATCH 0
|
| | 32 | +#define VERSION_PATCH 1
|
| 33 | 33 | #define VERSION_SVN "$REVISION$"
|
| 34 | 34 | #define VERSION_SVN_INT $REVISIONINT$
|
| 35 | 35 |
|
| Index: emcore/trunk/export/syscallapi.h |
| — | — | @@ -71,12 +71,12 @@ |
| 72 | 72 | #endif |
| 73 | 73 | |
| 74 | 74 | /* increase this every time the api struct changes */ |
| 75 | | -#define EMCORE_API_VERSION 2 |
| | 75 | +#define EMCORE_API_VERSION 3 |
| 76 | 76 | |
| 77 | 77 | /* update this to latest version if a change to the api struct breaks |
| 78 | 78 | backwards compatibility (and please take the opportunity to sort in any |
| 79 | 79 | new function which are "waiting" at the end of the function table) */ |
| 80 | | -#define EMCORE_MIN_API_VERSION 2 |
| | 80 | +#define EMCORE_MIN_API_VERSION 3 |
| 81 | 81 | |
| 82 | 82 | /* NOTE: To support backwards compatibility, only add new functions at |
| 83 | 83 | the end of the structure. Every time you add a new function, |
| Index: emcore/trunk/thread.c |
| — | — | @@ -93,6 +93,8 @@ |
| 94 | 94 | {
|
| 95 | 95 | obj->count = 1;
|
| 96 | 96 | obj->owner = current_thread;
|
| | 97 | + obj->owned_next = current_thread->owned_mutexes;
|
| | 98 | + current_thread->owned_mutexes = obj;
|
| 97 | 99 | }
|
| 98 | 100 | else if (obj->owner == current_thread) obj->count++;
|
| 99 | 101 | else
|
| — | — | @@ -117,6 +119,35 @@ |
| 118 | 120 | return ret;
|
| 119 | 121 | }
|
| 120 | 122 |
|
| | 123 | +void mutex_unlock_internal(struct mutex* obj)
|
| | 124 | +{
|
| | 125 | + struct mutex* o;
|
| | 126 | + if (!obj->owner->owned_mutexes) return;
|
| | 127 | + if (obj->owner->owned_mutexes == obj) obj->owner->owned_mutexes = obj->owned_next;
|
| | 128 | + else
|
| | 129 | + {
|
| | 130 | + o = obj->owner->owned_mutexes;
|
| | 131 | + while (o->owned_next)
|
| | 132 | + {
|
| | 133 | + if (o->owned_next == obj) o->owned_next = obj->owned_next;
|
| | 134 | + o = o->owned_next;
|
| | 135 | + }
|
| | 136 | + }
|
| | 137 | + if (obj->waiters)
|
| | 138 | + {
|
| | 139 | + obj->count = 1;
|
| | 140 | + obj->owner = obj->waiters;
|
| | 141 | + obj->waiters->state = THREAD_READY;
|
| | 142 | + obj->waiters->block_type = THREAD_NOT_BLOCKED;
|
| | 143 | + obj->waiters->blocked_by = NULL;
|
| | 144 | + obj->waiters->timeout = 0;
|
| | 145 | + obj->waiters = obj->waiters->queue_next;
|
| | 146 | + obj->owned_next = obj->owner->owned_mutexes;
|
| | 147 | + obj->owner->owned_mutexes = obj;
|
| | 148 | + }
|
| | 149 | + else obj->count = 0;
|
| | 150 | +}
|
| | 151 | +
|
| 121 | 152 | int mutex_unlock(struct mutex* obj)
|
| 122 | 153 | {
|
| 123 | 154 | int ret = THREAD_OK;
|
| — | — | @@ -133,18 +164,8 @@ |
| 134 | 165 | leave_critical_section(mode);
|
| 135 | 166 | panicf(PANIC_KILLTHREAD, "Trying to unlock mutex owned by different thread! (%08X)", obj);
|
| 136 | 167 | }
|
| 137 | | -
|
| 138 | 168 | if (--(obj->count)) ret = obj->count;
|
| 139 | | - else if (obj->waiters)
|
| 140 | | - {
|
| 141 | | - obj->count = 1;
|
| 142 | | - obj->owner = obj->waiters;
|
| 143 | | - obj->waiters->state = THREAD_READY;
|
| 144 | | - obj->waiters->block_type = THREAD_NOT_BLOCKED;
|
| 145 | | - obj->waiters->blocked_by = NULL;
|
| 146 | | - obj->waiters->timeout = 0;
|
| 147 | | - obj->waiters = obj->waiters->queue_next;
|
| 148 | | - }
|
| | 169 | + else mutex_unlock_internal(obj);
|
| 149 | 170 |
|
| 150 | 171 | leave_critical_section(mode);
|
| 151 | 172 | return ret;
|
| — | — | @@ -485,6 +506,10 @@ |
| 486 | 507 | thread->state = THREAD_SUSPENDED;
|
| 487 | 508 | }
|
| 488 | 509 |
|
| | 510 | + struct mutex* m;
|
| | 511 | + for (m = thread->owned_mutexes; m; m = m->owned_next)
|
| | 512 | + mutex_unlock_internal(m);
|
| | 513 | +
|
| 489 | 514 | leave_critical_section(mode);
|
| 490 | 515 |
|
| 491 | 516 | library_release_all_of_thread(thread);
|
| Index: emcore/trunk/thread.h |
| — | — | @@ -68,8 +68,10 @@ |
| 69 | 69 | };
|
| 70 | 70 |
|
| 71 | 71 |
|
| 72 | | -#define SCHEDULER_THREAD_INFO_VERSION 2
|
| | 72 | +#define SCHEDULER_THREAD_INFO_VERSION 3
|
| 73 | 73 |
|
| | 74 | +struct mutex;
|
| | 75 | +
|
| 74 | 76 | struct scheduler_thread
|
| 75 | 77 | {
|
| 76 | 78 | uint32_t regs[16];
|
| — | — | @@ -81,6 +83,7 @@ |
| 82 | 84 | uint32_t startusec;
|
| 83 | 85 | struct scheduler_thread* thread_next;
|
| 84 | 86 | struct scheduler_thread* queue_next;
|
| | 87 | + struct mutex* owned_mutexes;
|
| 85 | 88 | uint32_t timeout;
|
| 86 | 89 | uint32_t blocked_since;
|
| 87 | 90 | void* blocked_by;
|
| — | — | @@ -96,6 +99,7 @@ |
| 97 | 100 | {
|
| 98 | 101 | struct scheduler_thread* owner;
|
| 99 | 102 | struct scheduler_thread* waiters;
|
| | 103 | + struct mutex* owned_next;
|
| 100 | 104 | int count;
|
| 101 | 105 | };
|
| 102 | 106 |
|