Index: src/condition.h ================================================================== --- src/condition.h +++ src/condition.h @@ -18,11 +18,11 @@ #include "objfw-defs.h" #include "platform.h" #if !defined(OF_HAVE_THREADS) || \ - (!defined(OF_HAVE_PTHREADS) && !defined(OF_WINDOWS)) + (!defined(OF_HAVE_PTHREADS) && !defined(OF_WINDOWS) && !defined(OF_AMIGAOS)) # error No conditions available! #endif /* For of_time_interval_t */ #import "OFObject.h" @@ -34,11 +34,20 @@ typedef pthread_cond_t of_condition_t; #elif defined(OF_WINDOWS) # include typedef struct { HANDLE event; - int count; + volatile int count; +} of_condition_t; +#elif defined(OF_AMIGAOS) +# include +typedef struct { + struct of_condition_waiting_task { + struct Task *task; + uint8_t sigBit; + struct of_condition_waiting_task *next; + } *waitingTasks; } of_condition_t; #endif #ifdef __cplusplus extern "C" { Index: src/condition.m ================================================================== --- src/condition.m +++ src/condition.m @@ -21,6 +21,8 @@ #if defined(OF_HAVE_PTHREADS) # include "condition_pthread.m" #elif defined(OF_WINDOWS) # include "condition_winapi.m" +#elif defined(OF_AMIGAOS) +# include "condition_amiga.m" #endif ADDED src/condition_amiga.m Index: src/condition_amiga.m ================================================================== --- src/condition_amiga.m +++ src/condition_amiga.m @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, + * 2018, 2019 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#ifdef OF_AMIGAOS4 +# define __USE_INLINE__ +# define __NOLIBBASE__ +# define __NOGLOBALIFACE__ +#endif +#include +#include +#ifndef OF_AMIGAOS4 +# include +#endif + +#ifdef OF_AMIGAOS4 +extern struct ExecIFace *IExec; +#endif + +bool +of_condition_new(of_condition_t *condition) +{ + condition->waitingTasks = NULL; + + return true; +} + +bool +of_condition_signal(of_condition_t *condition) +{ + Forbid(); + @try { + if (condition->waitingTasks == NULL) + return true; + + Signal(condition->waitingTasks->task, + 1 << condition->waitingTasks->sigBit); + + condition->waitingTasks = condition->waitingTasks->next; + } @finally { + Permit(); + } + + return true; +} + +bool +of_condition_broadcast(of_condition_t *condition) +{ + Forbid(); + @try { + if (condition->waitingTasks == NULL) + return true; + + while (condition->waitingTasks != NULL) { + Signal(condition->waitingTasks->task, + 1 << condition->waitingTasks->sigBit); + + condition->waitingTasks = condition->waitingTasks->next; + } + } @finally { + Permit(); + } + + return true; +} + +bool +of_condition_wait(of_condition_t *condition, of_mutex_t *mutex) +{ + struct of_condition_waiting_task waitingTask = { + .task = FindTask(NULL), + .sigBit = AllocSignal(-1) + }; + + if (waitingTask.sigBit == -1) + return false; + + if (!of_mutex_unlock(mutex)) { + FreeSignal(waitingTask.sigBit); + return false; + } + + Forbid(); + + waitingTask.next = condition->waitingTasks; + condition->waitingTasks = &waitingTask; + + Wait(1 << waitingTask.sigBit); + Permit(); + + FreeSignal(waitingTask.sigBit); + + return true; +} + +bool +of_condition_timed_wait(of_condition_t *condition, of_mutex_t *mutex, + of_time_interval_t timeout) +{ + struct of_condition_waiting_task waitingTask = { + .task = FindTask(NULL), + .sigBit = AllocSignal(-1) + }; + struct MsgPort port = { + .mp_Node = { + .ln_Type = NT_MSGPORT + }, + .mp_Flags = PA_SIGNAL, + .mp_SigTask = waitingTask.task, + .mp_SigBit = AllocSignal(-1) + }; +#ifdef OF_AMIGAOS4 + struct TimeRequest request = { + .Request = { +#else + struct timerequest request = { + .tr_node = { +#endif + .io_Message = { + .mn_Node = { + .ln_Type = NT_MESSAGE + }, + .mn_ReplyPort = &port, + .mn_Length = sizeof(request) + }, + .io_Command = TR_ADDREQUEST + }, +#ifdef OF_AMIGAOS4 + .Time = { + .Seconds = (ULONG)timeout, + .Microseconds = + (timeout - request.Time.Seconds) * 1000000 +#else + .tr_time = { + .tv_sec = (ULONG)timeout, + .tv_micro = (timeout - request.tr_time.tv_sec) * 1000000 +#endif + } + }; + ULONG mask; + + NewList(&port.mp_MsgList); + + if (waitingTask.sigBit == -1 || port.mp_SigBit == -1) + goto fail; + + if (OpenDevice("timer.device", UNIT_MICROHZ, + (struct IORequest *)&request, 0) != 0) + goto fail; + + if (!of_mutex_unlock(mutex)) + goto fail; + + Forbid(); + + waitingTask.next = condition->waitingTasks; + condition->waitingTasks = &waitingTask; + + SendIO((struct IORequest *)&request); + + mask = Wait((1 << waitingTask.sigBit) | (1 << port.mp_SigBit)); + + condition->waitingTasks = waitingTask.next; + + if (!CheckIO((struct IORequest *)&request)) { + AbortIO((struct IORequest *)&request); + WaitIO((struct IORequest *)&request); + } + CloseDevice((struct IORequest *)&request); + + Permit(); + + if (!(mask & (1 << waitingTask.sigBit))) + goto fail; + + FreeSignal(waitingTask.sigBit); + FreeSignal(port.mp_SigBit); + + return true; + +fail: + if (waitingTask.sigBit != -1) + FreeSignal(waitingTask.sigBit); + if (port.mp_SigBit != -1) + FreeSignal(port.mp_SigBit); + + return false; +} + +bool +of_condition_free(of_condition_t *condition) +{ + Forbid(); + @try { + if (condition->waitingTasks != NULL) + return false; + } @finally { + Permit(); + } + + return true; +} Index: src/condition_winapi.m ================================================================== --- src/condition_winapi.m +++ src/condition_winapi.m @@ -13,12 +13,10 @@ * Public License, either version 2 or 3, which can be found in the file * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ -#include "config.h" - bool of_condition_new(of_condition_t *condition) { condition->count = 0; Index: src/thread_amiga.m ================================================================== --- src/thread_amiga.m +++ src/thread_amiga.m @@ -147,13 +147,15 @@ */ ADD_TAG(NP_Priority, (attr->priority > 0 ? attr->priority * 127 : attr->priority * 128)) } - ADD_TAG(NP_StackSize, (attr != NULL && attr->stackSize != 0 - ? (LONG)attr->stackSize - : ((struct Process *)FindTask(NULL))->pr_StackSize)) + if (attr != NULL && attr->stackSize != 0) + ADD_TAG(NP_StackSize, attr->stackSize) + else + ADD_TAG(NP_StackSize, + ((struct Process *)FindTask(NULL))->pr_StackSize) ADD_TAG(TAG_DONE, 0) #undef ADD_TAG (*thread)->task = (struct Task *)CreateNewProc(tags.items);