int main() { struct Process *child; struct TagItem tags[] = { { NP_Entry, (IPTR) entry }, { NP_Cli, (IPTR) TRUE }, { NP_Name, (IPTR) "test" }, { NP_NotifyOnDeath, (IPTR) TRUE }, { TAG_DONE, 0 } }; child = CreateNewProc(tags); if(child) { ULONG childid = GetETask((struct Task*) child)->et_UniqueID; Printf("Waiting for child with id %d\n", childid); ChildWait(childid); Printf("Child exited, freeing child\n"); ChildFree(childid); } else PrintFault(IoErr(), "Couldn't create child process"); return 0; }
int main() { tmpname = mktemp("T:flockXXXXXX"); int fd = open(tmpname, O_CREAT); TEST((fd != -1)); TEST((flock(fd, LOCK_SH|LOCK_NB) == 0)); TEST((flock(fd, LOCK_UN) == 0)); TEST((flock(fd, LOCK_EX|LOCK_NB) == 0)); TEST((flock(fd, LOCK_UN) == 0)); TEST((flock(fd, LOCK_SH) == 0)); TEST((flock(fd, LOCK_UN) == 0)); TEST((flock(fd, LOCK_EX) == 0)); TEST((flock(fd, LOCK_UN) == 0)); close(fd); /* Create NPROCS processes increasing counter ITERATIONS times in an ugly way */ int counter = 0; struct Process *procs[NPROCS]; ULONG ids[NPROCS]; struct TagItem tags[] = { { NP_Entry, (IPTR) entry }, { NP_Name, (IPTR) "flocker" }, { NP_Output, (IPTR) Output() }, { NP_CloseOutput, (IPTR) FALSE }, { NP_UserData, (IPTR) &counter }, { NP_NotifyOnDeath, (IPTR) TRUE }, { TAG_DONE, 0 } }; int i; InitSemaphore(&sem); for(i = 0; i < NPROCS; i++) { procs[i] = CreateNewProc(tags); TEST((procs[i])); ids[i] = GetETask(procs[i])->et_UniqueID; Signal((struct Task *)procs[i], SIGBREAKF_CTRL_C); } for(i = 0; i < NPROCS; i++) { ChildWait(ids[i]); ChildFree(ids[i]); } putchar('\n'); TEST((counter == NPROCS * ITERATIONS)); cleanup(); return OK; }
int uae_start_thread (const TCHAR *name, void *(*f)(void *), void *arg, uae_thread_id *tid) { struct MsgPort *replyport; struct Process *newtask = NULL; struct TagItem procTags[] = { { NP_Name, (IPTR) NULL}, { NP_StackSize, (IPTR)(64 * 1024)}, { NP_Entry, (IPTR) do_thread}, //{ NP_Output, Output ()}, //{ NP_Input, Input ()}, //{ NP_CloseOutput, FALSE}, //{ NP_CloseInput, FALSE}, { TAG_DONE, 0} }; #warning Do we need to care for priorities here? WinUAE does.. if(!name) procTags[0].ti_Data = (IPTR)default_name; else procTags[0].ti_Data = (IPTR)name; bug("[JUAE:PX] %s('%s', f %lx, arg %lx, tid %lx)\n", __PRETTY_FUNCTION__, procTags[0].ti_Data, f, arg, tid); replyport = CreateMsgPort(); if(!replyport) { write_log("ERROR: Unable to create MsgPort!\n"); } newtask = CreateNewProc (procTags); bug("[JUAE:PX] %s: Process @ %p, MsgPort @ %p\n", __PRETTY_FUNCTION__, newtask, newtask->pr_MsgPort); if(newtask) { struct startupmsg msg; msg.msg.mn_ReplyPort = replyport; msg.msg.mn_Length = sizeof msg; msg.func = f; msg.arg = arg; PutMsg (&newtask->pr_MsgPort, (struct Message*)&msg); WaitPort (replyport); } DeleteMsgPort (replyport); if(tid) { *tid=newtask; } return (newtask != 0); }
static int WBOpen(LIBBASETYPEPTR LIBBASE) { ObtainSemaphore(&(WorkbenchBase->wb_InitializationSemaphore)); if (!(WorkbenchBase->wb_Initialized)) { struct CommandLineInterface *cli; /* Duplicate the search path ---------------------------------------*/ if ((cli = Cli()) != NULL) { WorkbenchBase->wb_SearchPath = DuplicateSearchPath ( cli->cli_CommandDir ); } const struct TagItem tags[]= { {NP_Entry , (IPTR)WorkbenchHandler }, {NP_Name , (IPTR)"Workbench Handler" }, {NP_UserData , (IPTR)WorkbenchBase }, {NP_StackSize, 8129 }, {TAG_DONE , 0 } }; /* Start workbench handler -----------------------------------------*/ if ((CreateNewProc(tags)) != NULL) { /* Prevent expunging while the handler is running */ AROS_ATOMIC_INC(WorkbenchBase->LibNode.lib_OpenCnt); } else { // FIXME: free resources return FALSE; } WorkbenchBase->wb_Initialized = TRUE; } ReleaseSemaphore(&(WorkbenchBase->wb_InitializationSemaphore)); return TRUE; } /* L_OpenLib */
int main() { struct Process *child; struct TagItem tags[] = { { NP_Entry, (IPTR) entry }, { NP_Cli, (IPTR) TRUE }, { NP_Name, (IPTR) "test" }, { NP_NotifyOnDeath, (IPTR) TRUE }, { TAG_DONE, 0 } }; child = CreateNewProc(tags); if(child) { ULONG childstatus; ULONG childid = GetETask((struct Task*) child)->et_UniqueID; Printf("Checking status value for non-existing child id\n"); childstatus = ChildStatus(-1); assert(childstatus == CHILD_NOTFOUND); Printf("Result: CHILD_NOTFOUND\n"); Printf("Checking status value for running child id\n"); childstatus = ChildStatus(childid); assert(childstatus == CHILD_ACTIVE); Printf("Result: CHILD_ACTIVE\n"); ChildWait(childid); Printf("Checking status value for died child id\n"); childstatus = ChildStatus(childid); assert(childstatus == CHILD_EXITED); Printf("Result: CHILD_EXITED\n"); ChildFree(childid); Printf("Checking status value for freed child id\n"); childstatus = ChildStatus(childid); assert(childstatus == CHILD_NOTFOUND); Printf("Result: CHILD_NOTFOUND\n"); } else PrintFault(IoErr(), "Couldn't create child process"); return 0; }
ULONG _AHIsub_Start( ULONG Flags, struct AHIAudioCtrlDrv *AudioCtrl, struct DriverBase* AHIsubBase ) { struct FilesaveBase* FilesaveBase = (struct FilesaveBase*) AHIsubBase; 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; case FORMAT_WAVE: 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(AslRequest(dd->fs_FileReq,NULL)) { struct TagItem proctags[] = { { NP_Entry, (ULONG) SlaveEntry }, { NP_Name, (ULONG) LibName }, { NP_Priority, -1 }, // It's a number cruncher... { NP_StackSize, 10000, }, { TAG_DONE, 0 } }; Forbid(); dd->fs_SlaveTask = CreateNewProc( proctags ); if( dd->fs_SlaveTask != NULL ) { 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(AslRequest(dd->fs_RecFileReq,NULL)) { struct TagItem proctags[] = { { NP_Entry, (ULONG) RecSlaveEntry }, { NP_Name, (ULONG) LibName }, { NP_Priority, 1 }, // Make it steady... { TAG_DONE, 0 } }; Delay(TICKS_PER_SECOND); // Wait for window to close etc... Forbid(); dd->fs_RecSlaveTask = CreateNewProc( proctags ); if( dd->fs_RecSlaveTask != NULL ) { 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; }
pid_t __vfork(jmp_buf env) { struct Task *this = FindTask(NULL); struct vfork_data *udata = AllocMem(sizeof(struct vfork_data), MEMF_ANY | MEMF_CLEAR); if(udata == NULL) { errno = ENOMEM; longjmp(env, -1); } D(bug("__vfork: allocated udata %p\n", udata)); bcopy(env, &udata->vfork_jump, sizeof(jmp_buf)); struct TagItem tags[] = { { NP_Entry, (IPTR) launcher }, { NP_CloseInput, (IPTR) FALSE }, { NP_CloseOutput, (IPTR) FALSE }, { NP_CloseError, (IPTR) FALSE }, { NP_Cli, (IPTR) TRUE }, { NP_Name, (IPTR) "vfork()" }, { NP_UserData, (IPTR) udata }, { NP_NotifyOnDeath, (IPTR) TRUE }, { TAG_DONE, 0 } }; udata->parent = this; struct arosc_privdata *ppriv = __get_arosc_privdata(); udata->ppriv = ppriv; /* Store parent's vfork_data to restore it later */ udata->prev = __get_arosc_privdata()->acpd_vfork_data; D(bug("__vfork: Saved old parent's vfork_data: %p\n", udata->prev)); D(bug("__vfork: backuping startup buffer\n")); /* Backup startup buffer */ CopyMem(&__aros_startup_jmp_buf, &udata->startup_jmp_buf, sizeof(jmp_buf)); D(bug("__vfork: Allocating parent signal\n")); /* Allocate signal for child->parent communication */ udata->parent_signal = AllocSignal(-1); if(udata->parent_signal == -1) { /* Couldn't allocate the signal, return -1 */ FreeMem(udata, sizeof(struct vfork_data)); errno = ENOMEM; longjmp(udata->vfork_jump, -1); } D(bug("__vfork: Creating child\n")); udata->child = (struct Task*) CreateNewProc(tags); if(udata->child == NULL) { /* Something went wrong, return -1 */ FreeMem(udata, sizeof(struct vfork_data)); errno = ENOMEM; /* Most likely */ longjmp(env, -1); } D(bug("__vfork: Child created %p, waiting to finish setup\n", udata->child)); udata->child_id = GetETaskID(udata->child); D(bug("__vfork: Got unique child id: %d\n", udata->child_id)); /* Wait for child to finish setup */ Wait(1 << udata->parent_signal); if(udata->child_errno) { /* An error occured during child setup */ errno = udata->child_errno; longjmp(env, -1); } D(bug("__vfork: Setting jmp_buf at %p in %p\n", __aros_startup, &__aros_startup_jmp_buf)); if(setjmp(__aros_startup_jmp_buf)) { D(bug("__vfork: child exited\n or executed\n")); if(!GETUDATA->child_executed) { D(bug("__vfork: not executed\n")); ((struct aros_startup*) GetIntETask(GETUDATA->child)->iet_startup)->as_startup_error = __aros_startup_error; D(bug("__vfork: Signaling child\n")); Signal(GETUDATA->child, 1 << GETUDATA->child_signal); } D(bug("__vfork: Waiting for child to finish using udata\n")); /* Wait for child to finish using GETUDATA */ Wait(1 << GETUDATA->parent_signal); D(bug("__vfork: fflushing\n")); fflush(NULL); D(bug("__vfork: restoring old fd_array\n")); /* Restore parent's old fd_array */ ((struct arosc_privdata *) GetIntETask(GETUDATA->parent)->iet_acpd)->acpd_fd_mempool = GETUDATA->parent_acpd_fd_mempool; ((struct arosc_privdata *) GetIntETask(GETUDATA->parent)->iet_acpd)->acpd_numslots = GETUDATA->parent_acpd_numslots; ((struct arosc_privdata *) GetIntETask(GETUDATA->parent)->iet_acpd)->acpd_fd_array = GETUDATA->parent_acpd_fd_array; D(bug("__vfork: restoring startup buffer\n")); /* Restore parent startup buffer */ CopyMem(&GETUDATA->startup_jmp_buf, &__aros_startup_jmp_buf, sizeof(jmp_buf)); D(bug("__vfork: freeing parent signal\n")); FreeSignal(GETUDATA->parent_signal); errno = GETUDATA->child_errno; FreeAndJump(GETUDATA); assert(0); /* not reached */ return (pid_t) 1; } /* Remember parent fd descriptor table */ udata->parent_acpd_fd_mempool = ppriv->acpd_fd_mempool; udata->parent_acpd_numslots = ppriv->acpd_numslots; udata->parent_acpd_fd_array = ppriv->acpd_fd_array; /* Pretend to be running as the child created by vfork */ ppriv->acpd_vfork_data = udata; ppriv->acpd_flags |= PRETEND_CHILD; ppriv->acpd_fd_mempool = udata->cpriv->acpd_fd_mempool; ppriv->acpd_numslots = udata->cpriv->acpd_numslots; ppriv->acpd_fd_array = udata->cpriv->acpd_fd_array; D(bug("__vfork: Jumping to jmp_buf %p\n", &udata->vfork_jump)); D(bug("__vfork: ip: %p, stack: %p\n", udata->vfork_jump[0].retaddr, udata->vfork_jump[0].regs[_JMPLEN - 1])); vfork_longjmp(udata->vfork_jump, 0); assert(0); /* not reached */ return (pid_t) 0; }
// Launch a generic process int ASM L_IPC_Launch( REG(a0, struct ListLock *list), REG(a1, IPCData **storage), REG(a2, char *name), REG(d0, ULONG entry), REG(d1, ULONG stack), REG(d2, ULONG data), REG(a3, struct Library *dos_base), REG(a6, struct MyLibrary *libbase)) { struct LibData *libdata; IPCData *ipc; BOOL path=0; struct TagItem *tags; #ifdef __amigaos4__ libbase = dopuslibbase_global; #endif // Want path? if (stack&IPCF_GETPATH) path=1; // Get data pointer libdata=(struct LibData *)libbase->ml_UserData; // Clear storage if (storage) *storage=0; // Allocate data if (!(ipc=AllocVec(sizeof(IPCData),MEMF_CLEAR)) || !((tags=AllocVec(sizeof(struct TagItem)*8,MEMF_ANY)))) { FreeVec(ipc); return 0; } // Store memory and list pointers ipc->memory=libdata->memory; ipc->list=list; // Fill out process tags tags[0].ti_Tag=NP_Entry; tags[0].ti_Data = IPC_GET_ENTRY(entry); tags[1].ti_Tag=NP_Name; tags[1].ti_Data=(ULONG)name; tags[2].ti_Tag=NP_WindowPtr; tags[2].ti_Data=(ULONG)-1; tags[3].ti_Tag=NP_StackSize; tags[3].ti_Data=IPCM_STACK(stack); tags[4].ti_Tag=NP_Priority; tags[4].ti_Data=0; #if defined(__MORPHOS__) if (IPC_GET_CODETYPE(entry) == CODETYPE_PPC) { tags[3].ti_Tag = NP_CodeType; // Overwriting NP_StackSize (it is not required in PPC native code) tags[3].ti_Data = IPC_GET_CODETYPE(entry); } #endif // Want a path? if (path) { BPTR pathlist; #define DOpusBase (libdata->dopus_base) // Lock path list GetSemaphore(&libdata->path_lock,SEMF_SHARED,0); // Get path list copy pathlist=GetDosPathList(libdata->path_list); // Unlock path list FreeSemaphore(&libdata->path_lock); #undef DOpusBase // Fill out tags tags[5].ti_Tag=NP_Cli; tags[5].ti_Data=TRUE; tags[6].ti_Tag=NP_Path; tags[6].ti_Data=(ULONG)pathlist; tags[7].ti_Tag=TAG_END; } else tags[5].ti_Tag=TAG_END; #define DOSBase (dos_base) // Launch process ipc->proc=CreateNewProc(tags); #undef DOSBase // Free tags now FreeVec(tags); // Failed to launch? if (!ipc->proc) { FreeVec(ipc); return 0; } // Store pointer if (storage) *storage=ipc; // Send startup message return L_IPC_Startup(ipc,(APTR)data,0); }
static void __startup_detach(void) { struct CommandLineInterface *cli; struct Process *newproc; BPTR mysegment = NULL; STRPTR detached_name; D(bug("Entering __startup_detach(\"%s\", %d, %x)\n", argstr, argsize, SysBase)); cli = Cli(); /* Without a CLI detaching makes no sense, just jump to the real program. */ if (!cli) { __startup_entries_next(); } else { mysegment = cli->cli_Module; cli->cli_Module = NULL; detached_name = __detached_name ? __detached_name : (STRPTR)FindTask(NULL)->tc_Node.ln_Name; { struct TagItem tags[] = { { NP_Seglist, (IPTR)mysegment }, { NP_Entry, (IPTR)&__detach_trampoline }, { NP_Name, (IPTR)detached_name }, { NP_Arguments, (IPTR)__argstr }, { NP_Cli, TRUE }, { TAG_DONE, 0 } }; __detacher_process = (struct Process *)FindTask(NULL); /* CreateNewProc() will take care of freeing the seglist */ newproc = CreateNewProc(tags); } if (!newproc) { cli->cli_Module = mysegment; __detached_return_value = RETURN_ERROR; } else while (!__detacher_go_away) Wait(SIGF_SINGLE); if (__detached_return_value != RETURN_OK) { PutStr(FindTask(NULL)->tc_Node.ln_Name); PutStr(": Failed to detach.\n"); } if (newproc) { Forbid(); Signal(&newproc->pr_Task, SIGF_SINGLE); } __aros_startup.as_startup_error = __detached_return_value; } D(bug("Leaving __startup_detach\n")); }
static APTR createnewproctags(APTR DOSBase,ULONG Tag,...) { return CreateNewProc((struct TagItem *)&Tag); }