示例#1
0
文件: filter.c 项目: jalkanen/ppt
PERROR RunFilter( FRAME *frame, UBYTE *argstr )
{
    char argbuf[ARGBUF_SIZE];
    struct Process *p;
    PERROR res = PERR_OK;

    D(bug("RunFilter( %08X, %s )\n",frame,(argstr) ? argstr : (STRPTR)"NULL" ));

    LOCKGLOB();

    if( !IsAreaSelected(frame) ) {
        SelectWholeImage( frame );
    }

    D(bug("\tSelBox is (%d,%d)-(%d,%d)\n",frame->selbox.MinX, frame->selbox.MinY,
           frame->selbox.MaxX, frame->selbox.MaxY ));

    /*
     *  Reserve frame and lock windows
     */

    if(ObtainFrame( frame, BUSY_READONLY )) {

        if(argstr)
            sprintf(argbuf,"%lu %s",frame,argstr);
        else
            sprintf(argbuf,"%lu",frame);

#ifdef DEBUG_MODE
        p = CreateNewProcTags( NP_Entry, Filter, NP_Cli, FALSE,
            NP_Output, frame->debug_handle = OpenDebugFile( DFT_Effect ),
            NP_CloseOutput,TRUE, NP_Name, frame->nd.ln_Name,
            NP_StackSize, globals->userprefs->extstacksize,
            NP_Priority, globals->userprefs->extpriority, NP_Arguments, argbuf, TAG_END );
#else
        p = CreateNewProcTags( NP_Entry, Filter, NP_Cli, FALSE,
            NP_Output, Open("NIL:",MODE_NEWFILE),
            NP_CloseOutput, TRUE, NP_Name, frame->nd.ln_Name,
            NP_StackSize, globals->userprefs->extstacksize,
            NP_Priority, globals->userprefs->extpriority, NP_Arguments, argbuf, TAG_END );
#endif

        if(!p) {
            ReleaseFrame( frame );
            D(bug("\tCouldn't create a new process.\n"));
            res = PERR_GENERAL;
        } else {
            SetFrameStatus( frame, 1 );
            LOCK(frame);
            frame->currproc = p;
            UNLOCK(frame);
        }
    }

    UNLOCKGLOB();

    return res;
}
示例#2
0
bool Error_init(void){

	errortaskname=malloc(400);

	sprintf(errortaskname,"ErrorPortProc for: %s",screenname);

	InitSemaphore(&ErrorSemaphore);


	if(
		CreateNewProcTags(
			NP_Entry,ErrorProcess,
			NP_Name,errortaskname,
//			NP_Output,Open(constring,0x3ee),
			TAG_END
		)==NULL
	){
		fprintf(stderr,"Could not open Error Process\n");
		return false;
	}

	do{
		Delay(1);
	}while(ErrorTask==NULL);

	hassent=0;

	return true;
}
示例#3
0
static void* CreateConnectionData(DBusConnection* connection) {
  struct ConnectionData* c = AllocVec(sizeof(struct ConnectionData), MEMF_ANY|MEMF_CLEAR);

  kprintf("CreateConnectionData %08lx\n", c);
  
  if (c != NULL) {
    c->connection = connection;
    c->creator = FindTask(NULL);
    NewList((struct List*) &c->watches);
    
    Forbid();
    kprintf("creating mainloop\n");
    c->main   = (struct Task*) CreateNewProcTags(NP_Entry,    (ULONG) MainLoop,
						 NP_Name,     (ULONG) "dbus.library main loop",
						 NP_Priority, 0,
						 TAG_DONE);
    kprintf("created mainloop %08lx\n", c->main);
    if (c->main != NULL) {
      c->main->tc_UserData = c;
    }

    SetSignal(0, SIGF_SINGLE);
    Permit();

    Wait(SIGF_SINGLE);

    if (c->main == NULL) {
      DeleteConnectionData(c);
      c = NULL;
    }
  }

  return c;
}
示例#4
0
struct SysThread *Sys_Thread_CreateThread(void (*entrypoint)(void *), void *argument)
{
	struct SysThread *thread;

	thread = AllocVec(sizeof(*thread), MEMF_ANY);
	if (thread)
	{
		thread->msgport = CreateMsgPort();
		if (thread->msgport)
		{
			thread->msg.mn_Node.ln_Type = NT_MESSAGE;
			thread->msg.mn_ReplyPort = thread->msgport;
			thread->msg.mn_Length = sizeof(thread->msg);

			thread->entrypoint = entrypoint;
			thread->argument = argument;

			thread->process = CreateNewProcTags(NP_Entry, Sys_Thread_Trampoline,
			                                    NP_UserData, thread,
			                                    NP_Name, "Fodquake Thread",
			                                    NP_StackSize, 32768,
			                                    TAG_DONE);
			if (thread->process)
			{
				return thread;
			}

			DeleteMsgPort(thread->msgport);
		}
		FreeVec(thread);
	}

	return 0;
}
void __initdetach(void)
{ struct Library *DOSBase,*SysBase = *(struct Library **)4;
  struct SignalSemaphore *sema;

  if (_WBenchMsg)
    return;

  if ((sema=sem)) {        /* I must be the child process */
    ObtainSemaphore(sema); /* Assert that my parent is already dead */
    ReleaseSemaphore(sema);
    FreeMem(sema,sizeof(*sema));
    return;
  }
                          /* I must be the parent */
  if ((sem=sema=(struct SignalSemaphore *)AllocMem(sizeof(*sema),MEMF_PUBLIC|MEMF_CLEAR))) {

    InitSemaphore(sema);

    if ((DOSBase=OpenLibrary(__dosname,30))) {

      struct CommandLineInterface *cli = Cli();
      APTR pr,stack = __SaveSP;

      ObtainSemaphore(sema); /* Assert that my child is suspended until I'm finished */

      pr = CreateNewProcTags(NP_Seglist,cli->cli_Module, /* child process gets my seglist */
                             NP_FreeSeglist,1,           /* and must free it */
                             NP_Cli,1,                   /* it must be a CLI process */
                             NP_StackSize,__stack,       /* it gets a stack */
                             NP_Name,(ULONG)__procname,  /* a name */
                             NP_Priority,__priority,     /* a priority */
                             NP_Arguments,(ULONG)__commandline,/* and my commandline Arguments */
                             TAG_END);
      CloseLibrary(DOSBase);

      if (pr) {

        cli->cli_Module = 0; /* I'm no longer owner of this */

        /* Adjust stack, release semaphore and return 0 in one.
         * Maybe the 3 movel are a bit too cautious, but they ARE working
         */
        asm("movel %0,sp;movel %1,a6;movel %2,a0;moveql #0,d0;jmp a6@(-570)"::
            "r"(stack),"r"(SysBase),"r"(sema):"sp","a6","a0");
      }

      ReleaseSemaphore(sema); /* Again only caution - you never know */
    }
    FreeMem(sema,sizeof(*sema)); /* Couldn't start child :( */
  }
示例#6
0
int main(void)
{
    out = Output();

    slot1 = AllocTaskStorageSlot();
    FPrintf(out, "Got slot %ld\n", slot1);

    slot2 = AllocTaskStorageSlot();
    FPrintf(out, "Got slot %ld\n", slot2);

    FreeTaskStorageSlot(slot2);
    FPrintf(out, "Freed slot %ld\n", slot2);

    slot2 = AllocTaskStorageSlot();
    FPrintf(out, "Got slot %ld\n", slot2);

    slot3 = AllocTaskStorageSlot();
    FPrintf(out, "Got slot %ld\n", slot3);

    SetTaskStorageSlot(slot1, 69);
    FPrintf(out, "Stored value 69 in slot %ld\n", slot1);

    FPrintf(out, "Checking value in subtask\n");
    struct Process *proc = 
        CreateNewProcTags(
            NP_Entry, printslot1, NP_Name, "Check slot1",
            NP_Synchronous, TRUE, TAG_DONE
        );
    assert(proc != NULL);

    FreeTaskStorageSlot(slot1);
    FPrintf(out, "Freed slot %ld\n", slot1);

    slot1 = AllocTaskStorageSlot();
    FPrintf(out, "Got slot %ld\n", slot1);

    FreeTaskStorageSlot(slot2);
    FPrintf(out, "Freed slot %ld\n", slot2);

    FreeTaskStorageSlot(slot1);
    FPrintf(out, "Freed slot %ld\n", slot1);

    FreeTaskStorageSlot(slot3);
    FPrintf(out, "Freed slot %ld\n", slot3);

    return 0;
}
示例#7
0
int16 ASERDPort::open(uint16 config)
{
	// Don't open NULL name devices
	if (device_name == NULL)
		return openErr;

	// Init variables
	err_mask = 0;

	// Create message port
	reply_port = CreateMsgPort();
	if (reply_port == NULL)
		goto open_error;

	// Start process
	proc_error = false;
	proc_arg = this;
	SetSignal(0, SIGF_SINGLE);
	serial_proc = CreateNewProcTags(
		NP_Entry, (ULONG)serial_func,
		NP_Name, (ULONG)"Basilisk II Serial Task",
		NP_Priority, 1,
		TAG_END	
	);
	if (serial_proc == NULL)
		goto open_error;

	// Wait for signal from process
	Wait(SIGF_SINGLE);

	// Initialization error? Then bail out
	if (proc_error)
		goto open_error;

	// Configure port
	configure(config);
	return noErr;

open_error:
	serial_proc = NULL;
	if (reply_port) {
		DeleteMsgPort(reply_port);
		reply_port = NULL;
	}
	return openErr;
}
示例#8
0
bool ether_init(void)
{
	// Do nothing if no Ethernet device specified
	if (PrefsFindString("ether") == NULL)
		return false;

	// Initialize protocol list
	NewList(&prot_list);

	// Create message port
	reply_port = CreateMsgPort();
	if (reply_port == NULL)
		goto open_error;
	D(bug("signal mask %08lx\n", 1 << reply_port->mp_SigBit));

	// Start process
	proc_error = false;
	SetSignal(0, SIGF_SINGLE);
	net_proc = CreateNewProcTags(
		NP_Entry, (ULONG)net_func,
		NP_Name, (ULONG)"Basilisk II Ethernet Task",
		NP_Priority, 1,
		TAG_END
	);
	if (net_proc == NULL)
		goto open_error;

	// Wait for signal from process
	Wait(SIGF_SINGLE);

	// Initialization error? Then bail out
	if (proc_error)
		goto open_error;

	// Everything OK
	return true;

open_error:
	net_proc = NULL;
	if (reply_port) {
		DeleteMsgPort(reply_port);
		reply_port = NULL;
	}
	return false;
}
示例#9
0
struct Process *spawn( void *fn, char *name )
{
	struct Process *ret = (struct Process *) CreateNewProcTags (
	   			NP_Entry, 		(ULONG) fn,
				NP_Name,	   	name,
				NP_StackSize,   262144,
				NP_Child,		TRUE,
				NP_Priority,	0,
				NP_ExitData, 	IDOS,
				NP_FinalCode, spawn_died,
				TAG_DONE);

	if (ret) spawn_count ++;

	printf(" spawn count %d\n",spawn_count );

	return ret;
}
示例#10
0
	/**
	 * Create a sub process and start it, calling proc(param).
	 */
	ThreadObject_MorphOS(OTTDThreadFunc proc, void *param, self_destruct) :
		m_thr(0), self_destruct(self_destruct)
	{
		struct Task *parent;

		KPutStr("[OpenTTD] Create thread...\n");

		parent = FindTask(NULL);

		/* Make sure main thread runs with sane priority */
		SetTaskPri(parent, 0);

		/* Things we'll pass down to the child by utilizing NP_StartupMsg */
		m_msg.func = proc;
		m_msg.arg  = param;

		m_replyport = CreateMsgPort();

		if (m_replyport != NULL) {
			struct Process *child;

			m_msg.msg.mn_Node.ln_Type = NT_MESSAGE;
			m_msg.msg.mn_ReplyPort    = m_replyport;
			m_msg.msg.mn_Length       = sizeof(struct OTTDThreadStartupMessage);

			child = CreateNewProcTags(
				NP_CodeType,     CODETYPE_PPC,
				NP_Entry,        ThreadObject_MorphOS::Proxy,
				NP_StartupMsg,   (IPTR)&m_msg,
				NP_Priority,     5UL,
				NP_Name,         (IPTR)"OpenTTD Thread",
				NP_PPCStackSize, 131072UL,
				TAG_DONE);

			m_thr = (APTR) child;

			if (child != NULL) {
				KPutStr("[OpenTTD] Child process launched.\n");
			} else {
				KPutStr("[OpenTTD] Couldn't create child process. (constructors never fail, yeah!)\n");
				DeleteMsgPort(m_replyport);
			}
		}
	}
示例#11
0
void ShowAbout(void)
{
	struct Process *TaskMessage;

	if (choosing_flag == TRUE) return;


	struct pmpMessage *pmp = AllocVec(sizeof(struct pmpMessage), MEMF_SHARED);

	if(!pmp)
   	 return;

	pmp->about = "MPlayer - bounty version\n"
				"\nBuilt against MPlayer version: "	VERSION
				"\nAmiga version: " AMIGA_VERSION
				"\n" FFMPEG_VERSION
				"\n\nCopyright (C) MPlayer Team - http://www.mplayerhq.hu"
				"\n\nAmigaOS4 Version:"
				"\n\nAndrea Palmate' - http://www.amigasoft.net"
				"\nand Kjetil Hvalstrand (2014-2015) - http://database-org.com";

	pmp->type = REQTYPE_INFO;
	pmp->image = REQIMAGE_INFO;

	TaskMessage = (struct Process *) CreateNewProcTags (
		   							NP_Entry, 	(ULONG) PrintMsgProc,
						   			NP_Name,   	"About MPlayer",
									NP_StackSize,   262144,
									NP_Child,		TRUE,
									NP_Priority,	0,
					   				NP_EntryData, 	pmp,
					   				NP_ExitData, 	IDOS,
									NP_FinalCode, spawn_died,
						  			TAG_DONE);

	if (TaskMessage) spawn_count++;

	if (!TaskMessage)
	{
		PrintMsg(pmp->about,REQTYPE_INFO,REQIMAGE_INFO);
		FreeVec(pmp);
	}
}
示例#12
0
/*************
 * DESCRIPTION:   create a subtask
 * INPUT:         func     subtask function
 *                sigbit   signal bit for reply port
 *                name     name of the task
 *                priority
 *                stack
 * OUTPUT:        subtask structure
 *************/
struct SubTask *CreateSubTask(void (*func)(), LONG sigbit, char *name, ULONG priority, ULONG stack)
{
	struct SubTask *st;

	st = (struct SubTask*)AllocVec(sizeof(struct SubTask), MEMF_PUBLIC|MEMF_CLEAR);
	if(st)
	{
		st->st_Reply.mp_Node.ln_Name = NULL;
		st->st_Reply.mp_Node.ln_Pri = 0;
		st->st_Reply.mp_Node.ln_Type = NT_MSGPORT;
		st->st_Reply.mp_Flags = PA_SIGNAL;
		st->st_Reply.mp_SigBit = sigbit;
		st->st_Reply.mp_SigTask = (struct Task*)WARPOS_PPC_FUNC(FindTask)(NULL);
		NewList(&st->st_Reply.mp_MsgList);
		st->st_Task = (struct Task *)CreateNewProcTags(
			NP_Name, name,
			NP_Entry, func,
			NP_Priority, priority,
			NP_StackSize, stack,
			TAG_DONE);
		if(!st->st_Task)
		{
			FreeVec(st);
			st = NULL;
		}
		else
		{
			if(!SendSubTaskMsg(st, STC_STARTUP, st))
			{
				FreeVec(st);
				st = NULL;
			}
		}
	}
	return st;
}
示例#13
0
static struct AHIDevUnit *
InitUnit ( ULONG unit, 
           struct AHIBase *AHIBase )
{
  struct AHIDevUnit *iounit;

  if( unit == AHI_NO_UNIT )
  {
    ReadConfig(NULL,AHIBase);
    return NULL;
  }
  else if(!AHIBase->ahib_DevUnits[unit])
  {
    if((iounit = AllocVec(sizeof(struct AHIDevUnit), MEMF_CLEAR|MEMF_PUBLIC)))
    {
      NewList(&iounit->Unit.unit_MsgPort.mp_MsgList);

      iounit->Unit.unit_MsgPort.mp_Node.ln_Type = NT_MSGPORT;
      iounit->Unit.unit_MsgPort.mp_Flags = PA_IGNORE;
      iounit->Unit.unit_MsgPort.mp_Node.ln_Name = (STRPTR) DevName;
      iounit->UnitNum = unit;
      InitSemaphore(&iounit->ListLock);
      NewList((struct List *)&iounit->ReadList);
      NewList((struct List *)&iounit->PlayingList);
      NewList((struct List *)&iounit->SilentList);
      NewList((struct List *)&iounit->WaitingList);
      NewList((struct List *)&iounit->RequestQueue);
      if(ReadConfig(iounit,AHIBase))
      {
        if((iounit->Voices = AllocVec(
            sizeof(struct Voice)*iounit->Channels,MEMF_PUBLIC|MEMF_CLEAR)))
        {
          int i;
          struct Voice   *v = iounit->Voices;
          struct MsgPort *replyport;
          
          // Mark all channels as free
          for(i = 0 ; i < iounit->Channels; i++)
          {
            v->NextOffset = FREE;
            v++;
          }
          
          replyport = CreateMsgPort();

          if( replyport != NULL )
          {
            struct StartupMessage sm =
            {
              {
                { NULL, NULL, NT_UNKNOWN, 0, NULL },
                replyport, sizeof(struct StartupMessage),
              },
              iounit
            };

            iounit->Process = CreateNewProcTags( NP_Entry,    (ULONG) &DevProc,
                                                 NP_Name,     (ULONG) DevName,
                                                 NP_Priority, AHI_PRI,
                                                 TAG_DONE );

            if( iounit->Process != NULL )
            {
  
                PutMsg( &iounit->Process->pr_MsgPort,
                        &sm.Msg );

                WaitPort(replyport);
                GetMsg(replyport);
            }
            DeleteMsgPort(replyport);
          }
        }
      }

      if(!iounit->Process)
        FreeVec(iounit);
      else
        AHIBase->ahib_DevUnits[unit] = iounit;

    }
  }
  return AHIBase->ahib_DevUnits[unit];
}
示例#14
0
ULONG __asm __saveds intAHIsub_Start(
    register __d0 ULONG Flags,
    register __a2 struct AHIAudioCtrlDrv *AudioCtrl )
{
  AHIsub_Stop(Flags, AudioCtrl);

  if(Flags & AHISF_PLAY)
  {
    ULONG savebufferlength;

    if(!(dd->fs_MixBuffer = AllocVec(AudioCtrl->ahiac_BuffSize, MEMF_ANY)))
      return AHIE_NOMEM;

    dd->fs_SaveBufferSize = AudioCtrl->ahiac_MaxBuffSamples;

    // S16 has two buffers (L/R) instead
    if((AudioCtrl->ahiac_Flags & AHIACF_STEREO) && dd->fs_Format != FORMAT_S16)
    {
      dd->fs_SaveBufferSize <<=1;
    }

    if(dd->fs_SaveBufferSize < SAVEBUFFERSIZE)
    {
      dd->fs_SaveBufferSize = SAVEBUFFERSIZE;
    }

    savebufferlength = dd->fs_SaveBufferSize;


    switch(dd->fs_Format)
    {
      case FORMAT_8SVX:
        break;

      case FORMAT_AIFF:
        savebufferlength <<= 1;
        break;

      case FORMAT_AIFC:
        savebufferlength <<= 1;
        break;

      case FORMAT_S16:
        savebufferlength <<= 1;
        break;

      default:
        break;
    }


    if(!(dd->fs_SaveBuffer = AllocVec(savebufferlength, MEMF_ANY)))
    {
      return AHIE_NOMEM;
    }

    if ((AudioCtrl->ahiac_Flags & AHIACF_STEREO) && dd->fs_Format == FORMAT_S16)
    {
      if(!(dd->fs_SaveBuffer2 = AllocVec(savebufferlength, MEMF_ANY)))
      {
        return AHIE_NOMEM;
      }
    }

    if(AslRequestTags(dd->fs_FileReq,TAG_DONE))
    {

      Forbid();

      if(dd->fs_SlaveTask = CreateNewProcTags(
          NP_Entry,     SlaveEntry,
          NP_Name,      _LibName,
          NP_Priority,  -1,               // It's a number cruncher...
          NP_StackSize, 10000,
          TAG_DONE))
      {
        dd->fs_SlaveTask->pr_Task.tc_UserData = AudioCtrl;
      }

      Permit();

      if(dd->fs_SlaveTask)
      {
        Wait(1L<<dd->fs_MasterSignal);  // Wait for slave to come alive
        if(dd->fs_SlaveTask == NULL)    // Is slave alive or dead?
        {
          return AHIE_UNKNOWN;
        }
      }
      else
      {
        return AHIE_NOMEM;
      }
    }
    else
    {
      if(IoErr())
      {
        return AHIE_NOMEM;    //error occured
      }
      else
      {
        return AHIE_ABORTED;  //requester cancelled
      }
    }
  }

  if(Flags & AHISF_RECORD)
  {
    if(!(dd->fs_RecBuffer = AllocVec(RECBUFFERSIZE*4,MEMF_ANY)))
    {
      return AHIE_NOMEM;
    }

    if(AslRequestTags(dd->fs_RecFileReq,TAG_DONE))
    {
      Delay(TICKS_PER_SECOND);         // Wait for window to close etc...

      Forbid();

      if(dd->fs_RecSlaveTask = CreateNewProcTags(
          NP_Entry,     RecSlaveEntry,
          NP_Name,      _LibName,
          NP_Priority,  1,               // Make it steady...
          TAG_DONE))
      {
        dd->fs_RecSlaveTask->pr_Task.tc_UserData = AudioCtrl;
      }

      Permit();

      if(dd->fs_RecSlaveTask)
      {
        Wait(1L<<dd->fs_RecMasterSignal);  // Wait for slave to come alive
        if(dd->fs_RecSlaveTask == NULL)    // Is slave alive or dead?
        {
          return AHIE_UNKNOWN;
        }
      }
      else
      {
        return AHIE_NOMEM;
      }
    }
    else
    {
      if(IoErr())
      {
        return AHIE_NOMEM;    //error occured
      }
      else
      {
        return AHIE_ABORTED;  //requester cancelled
      }
    }
  }

  return AHIE_OK;
}
示例#15
0
文件: camdwait.c 项目: jgideonr/camd
SAVEDS void CamdTimerProc(void){
	struct timerequest *TimerIO;
	struct MsgPort  *TimerMP;
	ULONG sig;
	int error;

	D(bug("camdtimerproc1\n"));
	camdwaitsig=AllocSignal(-1);
	if(camdwaitsig==-1){
		camdwaitprocstatus=2;
		return;
	}
	D(bug("camdtimerproc2\n"));
	camdwaitsig2=AllocSignal(-1);
	if(camdwaitsig2==-1){
		FreeSignal(1L<<camdwaitsig);
		camdwaitprocstatus=2;
		return;
	}

	D(bug("camdtimerproc3\n"));
	TimerMP=CreateMsgPort();
	if(TimerMP==NULL){
		FreeSignal(1L<<camdwaitsig2);
		FreeSignal(1L<<camdwaitsig);
		camdwaitprocstatus=2;
		return;
	}
	D(bug("camdtimerproc4\n"));

	TimerIO=(struct timerequest *)AllocMem(sizeof(struct timerequest),MEMF_ANY|MEMF_CLEAR|MEMF_PUBLIC);
	D(bug("camdtimerproc5\n"));

	if(TimerIO==NULL){
		FreeSignal(1L<<camdwaitsig2);
		FreeSignal(1L<<camdwaitsig);
		DeleteMsgPort(TimerMP);
		camdwaitprocstatus=2;
		return;
	}
	D(bug("camdtimerproc6\n"));

	TimerIO->tr_node.io_Message.mn_Node.ln_Type=NT_MESSAGE;
	TimerIO->tr_node.io_Message.mn_ReplyPort=TimerMP;
	TimerIO->tr_node.io_Message.mn_Length=sizeof(struct timerequest);

	/* No support for eclock in AROS. */
#ifndef _AROS
	if((error=OpenDevice(
			TIMERNAME,UNIT_ECLOCK,(struct IORequest *)TimerIO,0L
	))!=0){
#else
	D(bug("camdtimerproc7\n"));
	if((error=OpenDevice(
			TIMERNAME,UNIT_VBLANK,(struct IORequest *)TimerIO,0L
	))!=0){
#endif
	  D(bug("camdtimerproc7.1\n"));
		FreeSignal(1L<<camdwaitsig2);
		FreeSignal(1L<<camdwaitsig);
		TimerIO->tr_node.io_Message.mn_Node.ln_Type=(UBYTE)-1;
		TimerIO->tr_node.io_Device=(struct Device *)-1L;
		TimerIO->tr_node.io_Unit=(struct Unit *)-1L;
		FreeMem(TimerIO,sizeof(struct timerequest));
		DeleteMsgPort(TimerMP);
		D(bug("failed camdtimerproc11, error: %ld\n",error));
		camdwaitprocstatus=2;
		return;
	}

	D(bug("camdtimerproc8\n"));
	ObtainSemaphore(&camdwaitsemaphore);

	D(bug("camdtimerproc9\n"));
	camdwaittask=FindTask(0L);

	camdwaitprocstatus=1;

	for(;;){
		sig=Wait(
			1L<<camdwaitsig |
			SIGBREAKF_CTRL_C
		);
		if(sig&SIGBREAKF_CTRL_C) break;

		if(sig & 1L<<camdwaitsig){				// Someone wants to obtain the semaphore?
			TimerIO->tr_node.io_Command=TR_ADDREQUEST;
			TimerIO->tr_time.tv_secs=0;
			TimerIO->tr_time.tv_micro=10;
			DoIO((struct IORequest *)TimerIO);	// ..Better let them wait.

			ReleaseSemaphore(&camdwaitsemaphore);		// Well, okey then.

			Wait(1L<<camdwaitsig2);					// Finished soon?

			ObtainSemaphore(&camdwaitsemaphore);		// But I want it back!
		}

	}

	ReleaseSemaphore(&camdwaitsemaphore);

	FreeSignal(1L<<camdwaitsig2);
	FreeSignal(1L<<camdwaitsig);
	CloseDevice((struct IORequest *)TimerIO);
	TimerIO->tr_node.io_Message.mn_Node.ln_Type=(UBYTE)-1;
	TimerIO->tr_node.io_Device=(struct Device *)-1L;
	TimerIO->tr_node.io_Unit=(struct Unit *)-1L;
	FreeMem(TimerIO,sizeof(struct timerequest));

	DeleteMsgPort(TimerMP);

	camdwaitprocstatus=3;

	return;
}

BOOL InitCamdTimer(void){
	struct Process *process;

	InitSemaphore(&camdwaitsemaphore);
	InitSemaphore(&camdwaitsemaphore2);

	process=CreateNewProcTags(
		NP_Entry,CamdTimerProc,
		NP_Name,"Camd Wait Proc",
		NP_Priority,5,
		TAG_END
	);
	if(process==NULL) return FALSE;

	D(bug("4.7\n"));
	while(camdwaitprocstatus==0) Delay(1);
	D(bug("4.8\n"));

	if(camdwaitprocstatus==2) return FALSE;

	return TRUE;
}

void UninitCamdTimer(void){

  if(camdwaitprocstatus==2) return;

  Signal(camdwaittask,SIGBREAKF_CTRL_C);
  while(camdwaitprocstatus!=3) Delay(1);
}



/*
 * When a hardware-sender buffer is full, or we are sending a sysex-message
 * to hardware, we need to wait for small amounts of time. That is what
 * this function tries to do.
 *
 */

void CamdWait(void){

	static BOOL iswaiting=FALSE;
	BOOL imjustgoingtoreturnsoon=iswaiting;

	ObtainSemaphore(&camdwaitsemaphore2);

		if(imjustgoingtoreturnsoon==TRUE){			// No big point having more than one visitor to wait.
			ReleaseSemaphore(&camdwaitsemaphore2);
			return;
		}

		iswaiting=TRUE;

		Signal(camdwaittask,1L<<camdwaitsig);		// Give me the semaphore!
		ObtainSemaphore(&camdwaitsemaphore);			// This should take some time.
			Signal(camdwaittask,1L<<camdwaitsig2);	// Okey, I've got it.
		ReleaseSemaphore(&camdwaitsemaphore);		// You're welcome.

		iswaiting=FALSE;

	ReleaseSemaphore(&camdwaitsemaphore2);

	return;
}