static void *queue (void *ctx) { int rc; void* be = zmq_socket(ctx, ZMQ_XREQ); assert (be); rc = zmq_bind(be, transport_be); assert (rc == 0); void* fe = zmq_socket(ctx, ZMQ_XREP); assert (fe); rc = zmq_bind(fe, transport_fe); assert (rc == 0); zmq_pollitem_t items[2]; items[0].socket = be; items[0].events = ZMQ_POLLIN; items[1].socket = fe; items[1].events = ZMQ_POLLIN; while (true) { items[0].revents = 0; items[1].revents = 0; int rc = zmq_poll(items, 2, 5000); if (rc < 0) { break; } if (rc > 0) { if (items[0].revents == ZMQ_POLLIN) { copy_msg(items[0].socket, items[1].socket); } if (items[1].revents == ZMQ_POLLIN) { copy_msg (items[1].socket, items[0].socket); } } } zmq_close(fe); zmq_close(be); return NULL; }
/** dump lruhash msg cache */ static int dump_msg_lruhash(SSL* ssl, struct worker* worker, struct lruhash* h) { struct lruhash_entry* e; struct query_info* k; struct reply_info* d; /* lruhash already locked by caller */ /* walk in order of lru; best first */ for(e=h->lru_start; e; e = e->lru_next) { regional_free_all(worker->scratchpad); lock_rw_rdlock(&e->lock); /* make copy of rrset in worker buffer */ if(!copy_msg(worker->scratchpad, e, &k, &d)) { lock_rw_unlock(&e->lock); return 0; } lock_rw_unlock(&e->lock); /* release lock so we can lookup the rrset references * in the rrset cache */ if(!dump_msg(ssl, k, d, *worker->env.now)) { return 0; } } return 1; }
static int log_ref_write(const char *ref_name, const unsigned char *old_sha1, const unsigned char *new_sha1, const char *msg) { int logfd, written, oflags = O_APPEND | O_WRONLY; unsigned maxlen, len; int msglen; char *log_file, *logrec; const char *committer; if (log_all_ref_updates < 0) log_all_ref_updates = !is_bare_repository(); log_file = git_path("logs/%s", ref_name); if (log_all_ref_updates && (!prefixcmp(ref_name, "refs/heads/") || !prefixcmp(ref_name, "refs/remotes/") || !strcmp(ref_name, "HEAD"))) { if (safe_create_leading_directories(log_file) < 0) return error("unable to create directory for %s", log_file); oflags |= O_CREAT; } logfd = open(log_file, oflags, 0666); if (logfd < 0) { if (!(oflags & O_CREAT) && errno == ENOENT) return 0; if ((oflags & O_CREAT) && errno == EISDIR) { if (remove_empty_directories(log_file)) { return error("There are still logs under '%s'", log_file); } logfd = open(log_file, oflags, 0666); } if (logfd < 0) return error("Unable to append to %s: %s", log_file, strerror(errno)); } adjust_shared_perm(log_file); msglen = msg ? strlen(msg) : 0; committer = git_committer_info(0); maxlen = strlen(committer) + msglen + 100; logrec = xmalloc(maxlen); len = sprintf(logrec, "%s %s %s\n", sha1_to_hex(old_sha1), sha1_to_hex(new_sha1), committer); if (msglen) len += copy_msg(logrec + len - 1, msg) - 1; written = len <= maxlen ? write_in_full(logfd, logrec, len) : -1; free(logrec); if (close(logfd) != 0 || written != len) return error("Unable to append to %s", log_file); return 0; }
static int msgs_flags_set( sync_vars_t *svars, int t ) { message_t *tmsg; copy_vars_t *cv; if (!(svars->state[t] & ST_SENT_FLAGS) || svars->flags_done[t] < svars->flags_total[t]) return 0; if ((svars->chan->ops[t] & OP_EXPUNGE) && (svars->ctx[t]->conf->trash || (svars->ctx[1-t]->conf->trash && svars->ctx[1-t]->conf->trash_remote_new))) { debug( "trashing in %s\n", str_ms[t] ); for (tmsg = svars->ctx[t]->msgs; tmsg; tmsg = tmsg->next) if (tmsg->flags & F_DELETED) { if (svars->ctx[t]->conf->trash) { if (!svars->ctx[t]->conf->trash_only_new || !tmsg->srec || tmsg->srec->uid[1-t] < 0) { debug( "%s: trashing message %d\n", str_ms[t], tmsg->uid ); svars->trash_total[t]++; stats( svars ); sync_ref( svars ); svars->drv[t]->trash_msg( svars->ctx[t], tmsg, msg_trashed, AUX ); if (deref_check_cancel( svars )) return -1; } else debug( "%s: not trashing message %d - not new\n", str_ms[t], tmsg->uid ); } else { if (!tmsg->srec || tmsg->srec->uid[1-t] < 0) { if (!svars->ctx[1-t]->conf->max_size || tmsg->size <= svars->ctx[1-t]->conf->max_size) { debug( "%s: remote trashing message %d\n", str_ms[t], tmsg->uid ); svars->trash_total[t]++; stats( svars ); cv = nfmalloc( sizeof(*cv) ); cv->cb = msg_rtrashed; cv->aux = INV_AUX; cv->srec = 0; cv->msg = tmsg; if (copy_msg( cv )) return -1; } else debug( "%s: not remote trashing message %d - too big\n", str_ms[t], tmsg->uid ); } else debug( "%s: not remote trashing message %d - not new\n", str_ms[t], tmsg->uid ); } } } svars->state[t] |= ST_SENT_TRASH; sync_close( svars, t ); return 0; }
static int log_ref_write(const char *ref_name, const unsigned char *old_sha1, const unsigned char *new_sha1, const char *msg) { int logfd, result, written, oflags = O_APPEND | O_WRONLY; unsigned maxlen, len; int msglen; char log_file[PATH_MAX]; char *logrec; const char *committer; if (log_all_ref_updates < 0) log_all_ref_updates = !is_bare_repository(); result = log_ref_setup(ref_name, log_file, sizeof(log_file)); if (result) return result; logfd = open(log_file, oflags); if (logfd < 0) return 0; msglen = msg ? strlen(msg) : 0; committer = git_committer_info(0); maxlen = strlen(committer) + msglen + 100; logrec = xmalloc(maxlen); len = sprintf(logrec, "%s %s %s\n", sha1_to_hex(old_sha1), sha1_to_hex(new_sha1), committer); if (msglen) len += copy_msg(logrec + len - 1, msg) - 1; written = len <= maxlen ? write_in_full(logfd, logrec, len) : -1; free(logrec); if (close(logfd) != 0 || written != len) return error("Unable to append to %s", log_file); return 0; }
static void box_loaded( int sts, void *aux ) { DECL_SVARS; sync_rec_t *srec; sync_rec_map_t *srecmap; message_t *tmsg; copy_vars_t *cv; flag_vars_t *fv; int uid, minwuid, *mexcs, nmexcs, rmexcs, no[2], del[2], todel, t1, t2; int sflags, nflags, aflags, dflags, nex; unsigned hashsz, idx; char fbuf[16]; /* enlarge when support for keywords is added */ if (check_ret( sts, aux )) return; INIT_SVARS(aux); svars->state[t] |= ST_LOADED; info( "%s: %d messages, %d recent\n", str_ms[t], svars->ctx[t]->count, svars->ctx[t]->recent ); if (svars->state[t] & S_FIND) { svars->state[t] &= ~S_FIND; debug( "matching previously copied messages on %s\n", str_ms[t] ); match_tuids( svars, t ); } debug( "matching messages on %s against sync records\n", str_ms[t] ); hashsz = bucketsForSize( svars->nsrecs * 3 ); srecmap = nfcalloc( hashsz * sizeof(*srecmap) ); for (srec = svars->srecs; srec; srec = srec->next) { if (srec->status & S_DEAD) continue; uid = srec->uid[t]; idx = (unsigned)((unsigned)uid * 1103515245U) % hashsz; while (srecmap[idx].uid) if (++idx == hashsz) idx = 0; srecmap[idx].uid = uid; srecmap[idx].srec = srec; } for (tmsg = svars->ctx[t]->msgs; tmsg; tmsg = tmsg->next) { if (tmsg->srec) /* found by TUID */ continue; uid = tmsg->uid; if (DFlags & DEBUG) { make_flags( tmsg->flags, fbuf ); printf( svars->ctx[t]->opts & OPEN_SIZE ? " message %5d, %-4s, %6lu: " : " message %5d, %-4s: ", uid, fbuf, tmsg->size ); } idx = (unsigned)((unsigned)uid * 1103515245U) % hashsz; while (srecmap[idx].uid) { if (srecmap[idx].uid == uid) { srec = srecmap[idx].srec; goto found; } if (++idx == hashsz) idx = 0; } tmsg->srec = 0; debug( "new\n" ); continue; found: tmsg->srec = srec; srec->msg[t] = tmsg; debug( "pairs %5d\n", srec->uid[1-t] ); } free( srecmap ); if ((t == S) && svars->smaxxuid) { debug( "preparing master selection - max expired slave uid is %d\n", svars->smaxxuid ); mexcs = 0; nmexcs = rmexcs = 0; minwuid = INT_MAX; for (srec = svars->srecs; srec; srec = srec->next) { if (srec->status & S_DEAD) continue; if (srec->status & S_EXPIRED) { if (!srec->uid[S] || ((svars->ctx[S]->opts & OPEN_OLD) && !srec->msg[S])) { srec->status |= S_EXP_S; continue; } } else { if (svars->smaxxuid >= srec->uid[S]) continue; } if (minwuid > srec->uid[M]) minwuid = srec->uid[M]; } debug( " min non-orphaned master uid is %d\n", minwuid ); for (srec = svars->srecs; srec; srec = srec->next) { if (srec->status & S_DEAD) continue; if (srec->status & S_EXP_S) { if (minwuid > srec->uid[M] && svars->maxuid[M] >= srec->uid[M]) { debug( " -> killing (%d,%d)\n", srec->uid[M], srec->uid[S] ); srec->status = S_DEAD; Fprintf( svars->jfp, "- %d %d\n", srec->uid[M], srec->uid[S] ); } else if (srec->uid[S]) { debug( " -> orphaning (%d,[%d])\n", srec->uid[M], srec->uid[S] ); Fprintf( svars->jfp, "> %d %d 0\n", srec->uid[M], srec->uid[S] ); srec->uid[S] = 0; } } else if (minwuid > srec->uid[M]) { if (srec->uid[S] < 0) { if (svars->maxuid[M] >= srec->uid[M]) { debug( " -> killing (%d,%d)\n", srec->uid[M], srec->uid[S] ); srec->status = S_DEAD; Fprintf( svars->jfp, "- %d %d\n", srec->uid[M], srec->uid[S] ); } } else if (srec->uid[M] > 0 && srec->uid[S] && (svars->ctx[M]->opts & OPEN_OLD) && (!(svars->ctx[M]->opts & OPEN_NEW) || svars->maxuid[M] >= srec->uid[M])) { if (nmexcs == rmexcs) { rmexcs = rmexcs * 2 + 100; mexcs = nfrealloc( mexcs, rmexcs * sizeof(int) ); } mexcs[nmexcs++] = srec->uid[M]; } } } debugn( " exception list is:" ); for (t = 0; t < nmexcs; t++) debugn( " %d", mexcs[t] ); debug( "\n" ); load_box( svars, M, minwuid, mexcs, nmexcs ); return; } if (!(svars->state[1-t] & ST_LOADED)) return; if (svars->uidval[M] < 0 || svars->uidval[S] < 0) { svars->uidval[M] = svars->ctx[M]->uidvalidity; svars->uidval[S] = svars->ctx[S]->uidvalidity; Fprintf( svars->jfp, "| %d %d\n", svars->uidval[M], svars->uidval[S] ); } info( "Synchronizing...\n" ); debug( "synchronizing new entries\n" ); svars->osrecadd = svars->srecadd; for (t = 0; t < 2; t++) { Fprintf( svars->jfp, "%c %d\n", "{}"[t], svars->ctx[t]->uidnext ); for (tmsg = svars->ctx[1-t]->msgs; tmsg; tmsg = tmsg->next) if (tmsg->srec ? tmsg->srec->uid[t] < 0 && (tmsg->srec->uid[t] == -1 ? (svars->chan->ops[t] & OP_RENEW) : (svars->chan->ops[t] & OP_NEW)) : (svars->chan->ops[t] & OP_NEW)) { debug( "new message %d on %s\n", tmsg->uid, str_ms[1-t] ); if ((svars->chan->ops[t] & OP_EXPUNGE) && (tmsg->flags & F_DELETED)) debug( " -> not %sing - would be expunged anyway\n", str_hl[t] ); else { if (tmsg->srec) { srec = tmsg->srec; srec->status |= S_DONE; debug( " -> pair(%d,%d) exists\n", srec->uid[M], srec->uid[S] ); } else { srec = nfmalloc( sizeof(*srec) ); srec->next = 0; *svars->srecadd = srec; svars->srecadd = &srec->next; svars->nsrecs++; srec->status = S_DONE; srec->flags = 0; srec->tuid[0] = 0; srec->uid[1-t] = tmsg->uid; srec->uid[t] = -2; Fprintf( svars->jfp, "+ %d %d\n", srec->uid[M], srec->uid[S] ); debug( " -> pair(%d,%d) created\n", srec->uid[M], srec->uid[S] ); } if ((tmsg->flags & F_FLAGGED) || !svars->chan->stores[t]->max_size || tmsg->size <= svars->chan->stores[t]->max_size) { if (tmsg->flags) { srec->flags = tmsg->flags; Fprintf( svars->jfp, "* %d %d %u\n", srec->uid[M], srec->uid[S], srec->flags ); debug( " -> updated flags to %u\n", tmsg->flags ); } for (t1 = 0; t1 < TUIDL; t1++) { t2 = arc4_getbyte() & 0x3f; srec->tuid[t1] = t2 < 26 ? t2 + 'A' : t2 < 52 ? t2 + 'a' - 26 : t2 < 62 ? t2 + '0' - 52 : t2 == 62 ? '+' : '/'; } svars->new_total[t]++; stats( svars ); cv = nfmalloc( sizeof(*cv) ); cv->cb = msg_copied; cv->aux = AUX; cv->srec = srec; cv->msg = tmsg; Fprintf( svars->jfp, "# %d %d %." stringify(TUIDL) "s\n", srec->uid[M], srec->uid[S], srec->tuid ); if (FSyncLevel >= FSYNC_THOROUGH) fdatasync( fileno( svars->jfp ) ); debug( " -> %sing message, TUID %." stringify(TUIDL) "s\n", str_hl[t], srec->tuid ); if (copy_msg( cv )) return; } else { if (tmsg->srec) { debug( " -> not %sing - still too big\n", str_hl[t] ); continue; } debug( " -> not %sing - too big\n", str_hl[t] ); msg_copied_p2( svars, srec, t, tmsg, -1 ); } } } svars->state[t] |= ST_SENT_NEW; msgs_copied( svars, t ); } debug( "synchronizing old entries\n" ); for (srec = svars->srecs; srec != *svars->osrecadd; srec = srec->next) { if (srec->status & (S_DEAD|S_DONE)) continue; debug( "pair (%d,%d)\n", srec->uid[M], srec->uid[S] ); no[M] = !srec->msg[M] && (svars->ctx[M]->opts & OPEN_OLD); no[S] = !srec->msg[S] && (svars->ctx[S]->opts & OPEN_OLD); if (no[M] && no[S]) { debug( " vanished\n" ); /* d.1) d.5) d.6) d.10) d.11) */ srec->status = S_DEAD; Fprintf( svars->jfp, "- %d %d\n", srec->uid[M], srec->uid[S] ); } else { del[M] = no[M] && (srec->uid[M] > 0); del[S] = no[S] && (srec->uid[S] > 0); for (t = 0; t < 2; t++) { srec->aflags[t] = srec->dflags[t] = 0; if (srec->msg[t] && (srec->msg[t]->flags & F_DELETED)) srec->status |= S_DEL(t); /* excludes (push) c.3) d.2) d.3) d.4) / (pull) b.3) d.7) d.8) d.9) */ if (!srec->uid[t]) { /* b.1) / c.1) */ debug( " no more %s\n", str_ms[t] ); } else if (del[1-t]) { /* c.4) d.9) / b.4) d.4) */ if (srec->msg[t] && (srec->msg[t]->status & M_FLAGS) && srec->msg[t]->flags != srec->flags) info( "Info: conflicting changes in (%d,%d)\n", srec->uid[M], srec->uid[S] ); if (svars->chan->ops[t] & OP_DELETE) { debug( " %sing delete\n", str_hl[t] ); svars->flags_total[t]++; stats( svars ); fv = nfmalloc( sizeof(*fv) ); fv->aux = AUX; fv->srec = srec; DRIVER_CALL(set_flags( svars->ctx[t], srec->msg[t], srec->uid[t], F_DELETED, 0, flags_set_del, fv )); } else debug( " not %sing delete\n", str_hl[t] ); } else if (!srec->msg[1-t]) /* c.1) c.2) d.7) d.8) / b.1) b.2) d.2) d.3) */ ; else if (srec->uid[t] < 0) /* b.2) / c.2) */ ; /* handled as new messages (sort of) */ else if (!del[t]) { /* a) & b.3) / c.3) */ if (svars->chan->ops[t] & OP_FLAGS) { sflags = srec->msg[1-t]->flags; if ((srec->status & (S_EXPIRE|S_EXPIRED)) && !t) sflags &= ~F_DELETED; srec->aflags[t] = sflags & ~srec->flags; srec->dflags[t] = ~sflags & srec->flags; if (DFlags & DEBUG) { char afbuf[16], dfbuf[16]; /* enlarge when support for keywords is added */ make_flags( srec->aflags[t], afbuf ); make_flags( srec->dflags[t], dfbuf ); debug( " %sing flags: +%s -%s\n", str_hl[t], afbuf, dfbuf ); } } else debug( " not %sing flags\n", str_hl[t] ); } /* else b.4) / c.4) */ } } } if ((svars->chan->ops[S] & (OP_NEW|OP_RENEW|OP_FLAGS)) && svars->chan->max_messages) { /* Flagged and not yet synced messages older than the first not * expired message are not counted. */ todel = svars->ctx[S]->count + svars->new_total[S] - svars->chan->max_messages; debug( "scheduling %d excess messages for expiration\n", todel ); for (tmsg = svars->ctx[S]->msgs; tmsg && todel > 0; tmsg = tmsg->next) if (!(tmsg->status & M_DEAD) && (srec = tmsg->srec) && ((tmsg->flags | srec->aflags[S]) & ~srec->dflags[S] & F_DELETED) && !(srec->status & (S_EXPIRE|S_EXPIRED))) todel--; debug( "%d non-deleted excess messages\n", todel ); for (tmsg = svars->ctx[S]->msgs; tmsg; tmsg = tmsg->next) { if (tmsg->status & M_DEAD) continue; if (!(srec = tmsg->srec) || srec->uid[M] <= 0) todel--; else { nflags = (tmsg->flags | srec->aflags[S]) & ~srec->dflags[S]; if (!(nflags & F_DELETED) || (srec->status & (S_EXPIRE|S_EXPIRED))) { if (nflags & F_FLAGGED) todel--; else if ((!(tmsg->status & M_RECENT) || (tmsg->flags & F_SEEN)) && (todel > 0 || ((srec->status & (S_EXPIRE|S_EXPIRED)) == (S_EXPIRE|S_EXPIRED)) || ((srec->status & (S_EXPIRE|S_EXPIRED)) && (tmsg->flags & F_DELETED)))) { srec->status |= S_NEXPIRE; debug( " pair(%d,%d)\n", srec->uid[M], srec->uid[S] ); todel--; } } } } debug( "%d excess messages remain\n", todel ); for (srec = svars->srecs; srec; srec = srec->next) { if ((srec->status & (S_DEAD|S_DONE)) || !srec->msg[S]) continue; nex = (srec->status / S_NEXPIRE) & 1; if (nex != ((srec->status / S_EXPIRED) & 1)) { if (nex != ((srec->status / S_EXPIRE) & 1)) { Fprintf( svars->jfp, "~ %d %d %d\n", srec->uid[M], srec->uid[S], nex ); debug( " pair(%d,%d): %d (pre)\n", srec->uid[M], srec->uid[S], nex ); srec->status = (srec->status & ~S_EXPIRE) | (nex * S_EXPIRE); } else debug( " pair(%d,%d): %d (pending)\n", srec->uid[M], srec->uid[S], nex ); } } } debug( "synchronizing flags\n" ); for (srec = svars->srecs; srec != *svars->osrecadd; srec = srec->next) { if (srec->status & (S_DEAD|S_DONE)) continue; for (t = 0; t < 2; t++) { aflags = srec->aflags[t]; dflags = srec->dflags[t]; if ((t == S) && ((mvBit(srec->status, S_EXPIRE, S_EXPIRED) ^ srec->status) & S_EXPIRED)) { if (srec->status & S_NEXPIRE) aflags |= F_DELETED; else dflags |= F_DELETED; } if ((svars->chan->ops[t] & OP_EXPUNGE) && (((srec->msg[t] ? srec->msg[t]->flags : 0) | aflags) & ~dflags & F_DELETED) && (!svars->ctx[t]->conf->trash || svars->ctx[t]->conf->trash_only_new)) { srec->aflags[t] &= F_DELETED; aflags &= F_DELETED; srec->dflags[t] = dflags = 0; } if (srec->msg[t] && (srec->msg[t]->status & M_FLAGS)) { aflags &= ~srec->msg[t]->flags; dflags &= srec->msg[t]->flags; } if (aflags | dflags) { svars->flags_total[t]++; stats( svars ); fv = nfmalloc( sizeof(*fv) ); fv->aux = AUX; fv->srec = srec; fv->aflags = aflags; fv->dflags = dflags; DRIVER_CALL(set_flags( svars->ctx[t], srec->msg[t], srec->uid[t], aflags, dflags, flags_set_sync, fv )); } else flags_set_sync_p2( svars, srec, t ); } } for (t = 0; t < 2; t++) { svars->drv[t]->commit( svars->ctx[t] ); svars->state[t] |= ST_SENT_FLAGS; if (msgs_flags_set( svars, t )) return; } }
int8_t ipc_handle_syscall(ProcessId_t o, uint8_t call_type, message_t* msg) { Process_t* src = process_manager_current_process; Process_t* dst = NULL; if (src->pid == o) { return IPC_DEADLOCK; } if (call_type == IPC_RECEIVE_ASYNC && src->ipc.sender.head == NULL) { return IPC_NOTHING_RECEIVED; } if (o == PROCESS_STDIN) { o = src->stdin; } else if (o == PROCESS_STDOUT) { o = src->stdout; } if (o == PROCESS_INVALID_ID) { return IPC_OTHER_NOT_FOUND; } else if ((call_type & IPC_RECEIVE) != IPC_RECEIVE || o != PROCESS_ANY) { /* allow ANY only on receive */ dst = process_manager_get_process_byid(o); if (dst == NULL) { return IPC_OTHER_NOT_FOUND; } } src->ipc.other = o; src->ipc.msg = mmu_get_physical_address(src->page_table, msg); switch (call_type) { case IPC_SEND: case IPC_SENDREC: /* SEND is falling through here */ _disable_interrupts(); if (dst->state == PROCESS_ZOMBIE) { _enable_interrupts(); return IPC_DEAD; } if (dst->state == PROCESS_BLOCKED && dst->ipc.call_type == IPC_RECEIVE && (dst->ipc.other == src->pid || dst->ipc.other == PROCESS_ANY)) { logger_debug("IPC: SEND-copying src=%i:%s dst=%i:%s", src->pid, src->name, o, (dst != NULL) ? dst->name : "<ANY>"); if (dst->ipc.other == PROCESS_ANY) { dst->ipc.other = src->pid; } _enable_interrupts(); /* both process are now BLOCKED */ copy_msg(src, dst); dst->ipc.call_type = IPC_NOOP; process_manager_set_process_ready(dst); } else { logger_debug("IPC: SEND-blocked src=%i:%s dst=%i:%s", src->pid, src->name, o, (dst != NULL) ? dst->name : "<ANY>"); if (dst->ipc.other == src->pid && dst->ipc.call_type & IPC_SEND) { return IPC_DEADLOCK; } src->ipc.call_type = IPC_SEND; /* place msg for later delivery into the IPC queue of the destination */ linked_list_add(&dst->ipc.sender, src); /* TODO: check for too less memory */ /* pause process */ process_manager_block_current_process(); process_manager_run_process(dst); _enable_interrupts(); } /* msg delivered, falling through receive except for send only */ if (call_type == IPC_SEND) { break; } case IPC_RECEIVE: /* SENDREC and SEND are falling through here */ case IPC_RECEIVE_ASYNC: _disable_interrupts(); if (dst != NULL) { if (dst->state == PROCESS_ZOMBIE) { _enable_interrupts(); return IPC_DEAD; } } else { /* receiving from ANY, maybe someone is already sending to this process */ linked_list_node_t* node; do { node = linked_list_pop_head(&src->ipc.sender); if (node != NULL) { dst = node->value; free(node); } } while (dst != NULL && dst->state == PROCESS_ZOMBIE); } if (dst != NULL && dst->state == PROCESS_BLOCKED && (dst->ipc.call_type & IPC_SEND) == IPC_SEND && dst->ipc.other == src->pid) { logger_debug("IPC: RECIEVED-copying src=%i:%s dst=%i:%s", src->pid, src->name, o, (dst != NULL) ? dst->name : "<ANY>"); /* both process are now BLOCKED */ _enable_interrupts(); /* remove sender out of sender list */ if (o != PROCESS_ANY) { linked_list_node_t* node = src->ipc.sender.head; while (node != NULL) { Process_t* p = node->value; if (p->pid == o) { linked_list_remove(&src->ipc.sender, node); break; } node = node->next; } } copy_msg(dst, src); dst->ipc.call_type = IPC_NOOP; process_manager_set_process_ready(dst); } else { if (dst != NULL && dst->ipc.other == src->pid && dst->ipc.call_type == IPC_RECEIVE) { return IPC_DEADLOCK; } src->ipc.call_type = IPC_RECEIVE; /* wait for msg delivery */ process_manager_block_current_process(); process_manager_run_process(dst); if (dst->state == PROCESS_ZOMBIE) { _enable_interrupts(); return IPC_DEAD; } logger_debug("IPC: RECIEVED-blocked src=%i:%s dst=%i:%s", src->pid, src->name, o, (dst != NULL) ? dst->name : "<ANY>"); _enable_interrupts(); /* msg received */ } break; } return IPC_OK; }