/* INCEPTION: My tribute to Christopher Nolan; The code below tries to explain and follow the sequence of events that took place in Inception; as seen from the eyes of the programmer. It performs the inception through a clever trick; using x86 code morphing technique in inception.h. This is done so as to make it appear that the thought; about copying the inception string was done by Fischer himself even though he expected to return to; a different state in real life.;; Copyright (C) 2010-2011 A.R.Karthick;;; This program is free software; you can redistribute it and/or modify; it under the terms of the GNU General Public License as published by; the Free Software Foundation; either version 2 of the License, or; (at your option) any later version.;; This program is distributed in the hope that it will be useful,; but WITHOUT ANY WARRANTY; without even the implied warranty of; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the; GNU General Public License for more details.;; You should have received a copy of the GNU General Public License; along with this program; if not, write to the Free Software; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA;;*/#include#include#include#include#include#include#include#include#include#ifdef __linux__#include#define GET_TID syscall(SYS_gettid)#else#define GET_TID ({0;})#endif#include "list.h"#include "inception_arch.h"#define DREAM_INCEPTION_TARGET 0x1#define DREAM_INCEPTION_PERFORMER 0x2#define DREAM_WORLD_ARCHITECT 0x4#define DREAM_ORGANIZER 0x8#define DREAM_SHAPES_FAKER 0x10#define DREAM_SEDATIVE_CREATOR 0x20#define DREAM_OVERLOOKER 0x40#define DREAM_ROLE_MASK 0x7f#define DREAMERS (0x7)/** fprintf output buffer is thread-safe anyway. So don't care much*/#define output(fmt, arg...) do { fprintf(stdout, fmt, ##arg);} while(0)#define DREAM_LEVELS (0x3 + 1 ) /* + 1 as an illustrative considering the 4th is really a limbo from 3rd */struct dreamer_request{#define DREAMER_HIJACKED 0x1#define DREAMER_DEFENSE_PROJECTIONS (0x2)#define DREAMER_FREE_FALL (0x4)#define DREAMER_FAKE_SHAPE (0x8)#define DREAMER_SHOT (0x10)#define DREAMER_KILLED (0x20)#define DREAMER_NEXT_LEVEL (0x40)#define DREAMER_IN_LIMBO (0x80)#define DREAMER_IN_MY_DREAM (0x100) /*shared dream*/#define DREAMER_KICK_BACK (0x200)#define DREAMER_FIGHT (0x400)#define DREAMER_SELF (0x800)#define DREAMER_FALL (0x1000)#define DREAMER_SYNCHRONIZE_KICK (0x2000)#define DREAMER_RECOVER (0x4000)struct dreamer_attr *dattr; /*dreamer attribute*/int cmd; /* request cmd */void *arg; /* request cmd arg*/struct list list; /* list head marker*/};struct dreamer_attr{const char *name;int role;int shared_state; /* shared request command state*/int level; /*dreamer level*/struct list_head request_queue; /* per dreamer request queue*/struct list list; /* list head marker*/pthread_mutex_t mutex;pthread_cond_t *cond[DREAM_LEVELS]; /* per dreamer wake up levels */};static pthread_mutex_t inception_reality_mutex = PTHREAD_MUTEX_INITIALIZER;static pthread_cond_t inception_reality_wakeup_for_all = PTHREAD_COND_INITIALIZER;static struct list_head dreamer_queue[DREAM_LEVELS];static pthread_mutex_t dreamer_mutex[DREAM_LEVELS];static pthread_mutex_t limbo_mutex = PTHREAD_MUTEX_INITIALIZER;static pthread_cond_t limbo_cond = PTHREAD_COND_INITIALIZER;#define _INCEPTION_C_#include "inception.h"static char *fischers_mind_state;static struct dreamer_attr *fischer_level1;static pid_t fischer_level1_taskid; /*fischers level1 taskid*/static int dream_delay_map[DREAM_LEVELS] = { 1, 2, 4, 8};static int dreamers_in_reality;static void fischer_dream_level1(void) __attribute__((unused));/** Queue the command to the dreamers request queue*/static void __dream_enqueue_cmd(struct dreamer_attr *dattr, int cmd, void *arg, int level, int locked){struct dreamer_request *req = calloc(1, sizeof(*req));assert(req != NULL);assert(level > 0 && level <= DREAM_LEVELS);req->dattr = dattr;req->cmd = cmd;req->arg = arg;if(!locked)pthread_mutex_lock(&dattr->mutex);list_add_tail(&req->list, &dattr->request_queue);pthread_cond_signal(dattr->cond[level-1]);if(!locked)pthread_mutex_unlock(&dattr->mutex);}static __inline__ void dream_enqueue_cmd(struct dreamer_attr *dattr, int cmd, void *arg, int level){return __dream_enqueue_cmd(dattr, cmd, arg, level, 0);}static __inline__ void dream_enqueue_cmd_safe(struct dreamer_attr *dattr, int cmd,void *arg, int level, pthread_mutex_t *dreamer_lock){/** Drop the current level dreamer lock before reacquiring.*/pthread_mutex_unlock(dreamer_lock);__dream_enqueue_cmd(dattr, cmd, arg, level, 0);pthread_mutex_lock(dreamer_lock);}static __inline__ void dream_enqueue_cmd_locked(struct dreamer_attr *dattr, int cmd, void *arg, int level){return __dream_enqueue_cmd(dattr, cmd, arg, level, 1);}/** Clone the request command to all the dreamers: Called with lock held.*/static void dream_clone_cmd(struct list_head *dreamer_queue, int cmd, void *arg, struct dreamer_attr *dattr, int level){register struct list *iter;for(iter = dreamer_queue->head; iter; iter = iter->next){struct dreamer_attr *dreamer = LIST_ENTRY(iter, struct dreamer_attr, list);if(dattr && dreamer == dattr)continue; /*skip cloning it on this dreamer*/dream_enqueue_cmd(dreamer, cmd, arg, level);}}static struct dreamer_request *dream_dequeue_cmd_locked(struct dreamer_attr *dattr){struct dreamer_request *req = NULL;struct list *head = NULL;if(!dattr->request_queue.nodes)return NULL;head = dattr->request_queue.head;assert(head != NULL);req = LIST_ENTRY(head, struct dreamer_request, list);list_del(head, &dattr->request_queue);return req;}static __inline__ struct dreamer_request *dream_dequeue_cmd(struct dreamer_attr *dattr){struct dreamer_request *req;pthread_mutex_lock(&dattr->mutex);req = dream_dequeue_cmd_locked(dattr);pthread_mutex_unlock(&dattr->mutex);return req;}static struct dreamer_attr *dreamer_find(struct list_head *dreamer_queue, const char *name, int role){register struct list *iter;for(iter = dreamer_queue->head; iter ; iter = iter->next){struct dreamer_attr *dattr = LIST_ENTRY(iter, struct dreamer_attr, list);if(role && (dattr->role & role))return dattr;if(name &&!strcasecmp(dattr->name, name))return dattr;}return NULL;}static struct dreamer_attr *dreamer_find_sync_locked(struct dreamer_attr *dreamer, int level, const char *name, int role){struct dreamer_attr *dattr = NULL;if(!level) return NULL;rescan:dattr = dreamer_find(&dreamer_queue[level-1], name, role);if(!dattr){static int c;pthread_mutex_unlock(&dreamer_mutex[level-1]);if(++c >= 10){output("[%s] waiting for [%s] to join at level [%d]\n", dreamer->name,name ?:"Unknown", level);}usleep(100000);pthread_mutex_lock(&dreamer_mutex[level-1]);goto rescan;}return dattr;}static struct dreamer_attr *dreamer_find_sync(struct dreamer_attr *dreamer, int level, const char *name, int role){struct dreamer_attr *dattr;if(!level) return NULL;pthread_mutex_lock(&dreamer_mutex[level-1]);dattr = dreamer_find_sync_locked(dreamer, level, name, role);pthread_mutex_unlock(&dreamer_mutex[level-1]);return dattr;}/** In a dream, you run 12 times slower : 5 mins of realtime = 60 mins* Fake the slowness by reduction in threads priority or the* scheduling priority of the dreamer*/static void set_thread_priority(struct dreamer_attr *dattr, int level){struct sched_param dream_param = {0};int policy = 0;assert(pthread_getschedparam(pthread_self(), &policy, &dream_param) == 0);if(dream_param.sched_priority > 12)dream_param.sched_priority -= 12;output("Dreamer [%s], level [%d], priority [%d], policy [%s]\n",dattr->name, level, dream_param.sched_priority,policy == SCHED_FIFO ? "FIFO" :(policy == SCHED_RR ? "RR" : "OTHER"));assert(pthread_setschedparam(pthread_self(), policy, &dream_param) == 0);}/** Wake up an individual dreamer in one level and let him propagate the kick down to levels below.*/static void wake_up_dreamer(struct dreamer_attr *dattr, int level){register struct list *iter;if(!level || (dattr->shared_state & DREAMER_IN_LIMBO)) return;pthread_mutex_lock(&dreamer_mutex[level-1]);for(iter = dreamer_queue[level-1].head; iter; iter = iter->next){struct dreamer_attr *dreamer = LIST_ENTRY(iter, struct dreamer_attr, list);if( !(dreamer->role ^ dattr->role) ){dream_enqueue_cmd(dreamer, DREAMER_KICK_BACK, NULL, dreamer->level);break;}}pthread_mutex_unlock(&dreamer_mutex[level-1]);}/** Level 0 is wake up dreamers on all levels.* Skip guys in a limbo from that level to all the way down.*/static void wake_up_dreamers(int level){int start = DREAM_LEVELS-1,end = 0;register int i;if(level > 0){start = level - 1;end = level - 1;}for(i = start; i >= end; --i){struct list *iter;pthread_mutex_lock(&dreamer_mutex[i]);for(iter = dreamer_queue[i].head; iter; iter = iter->next){struct dreamer_attr *dattr = LIST_ENTRY(iter, struct dreamer_attr, list);if( (dattr->shared_state & DREAMER_IN_LIMBO) )continue;dream_enqueue_cmd(dattr, DREAMER_KICK_BACK, NULL, dattr->level);}pthread_mutex_unlock(&dreamer_mutex[i]);}}/** Update states on all the levels and down.*/static void set_state(struct dreamer_attr *dattr, int state){register int i;for(i = DREAM_LEVELS - 1; i >= 0; --i){register struct list *iter;pthread_mutex_lock(&dreamer_mutex[i]);for(iter = dreamer_queue[i].head; iter; iter = iter->next){struct dreamer_attr *dreamer = LIST_ENTRY(iter, struct dreamer_attr, list);if(!(dreamer->role ^ dattr->role)){dreamer->shared_state |= state;break;}}pthread_mutex_unlock(&dreamer_mutex[i]);}}/** Set the limbo state on all levels of this dreamer so he cannot get a kick back* Called with the lock on that level.*/static void set_limbo_state(struct dreamer_attr *dattr){set_state(dattr, DREAMER_IN_LIMBO);}/** Called with the dreamer attr mutex held for the appropriate level.*/static void wait_for_kick(struct dreamer_attr *dattr){struct dreamer_request *req = NULL;for(;;){struct timespec ts = {0};while ( (req = dream_dequeue_cmd_locked(dattr)) ){if(req->cmd == DREAMER_KICK_BACK){free(req);if(dattr->level > 1){output("[%s] got Kick at level [%d]. Exiting back to level [%d]\n",dattr->name, dattr->level, dattr->level - 1);}else{output("[%s] got Kick at level [%d]. Exiting back to reality\n",dattr->name, dattr->level);}goto out;}free(req);}arch_gettime(dream_delay_map[dattr->level-1], &ts);pthread_cond_timedwait(dattr->cond[dattr->level-1], &dattr->mutex, &ts);}out:return;}static struct dreamer_attr *dream_attr_clone(int level, struct dreamer_attr *dattr){struct dreamer_attr *dattr_clone = calloc(1, sizeof(*dattr_clone));assert(dattr_clone != NULL);memcpy(dattr_clone, dattr, sizeof(*dattr_clone));dattr_clone->level = level;memset(&dattr_clone->mutex, 0, sizeof(dattr_clone->mutex));assert(pthread_mutex_init(&dattr_clone->mutex, NULL) == 0);list_init(&dattr_clone->request_queue);return dattr_clone;}static __inline__ void dream_level_create(int level, void * (*dream_function) (void *), struct dreamer_attr *dattr){pthread_attr_t attr;pthread_t dream;struct dreamer_attr *dattr_clone = dream_attr_clone(level, dattr);assert(dattr_clone != NULL);assert(pthread_attr_init(&attr)==0);assert(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) == 0);assert(pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED)==0);assert(pthread_create(&dream, &attr, dream_function, dattr_clone) == 0);}/** Now this is the state where Cobb. meets Saito.* The beauty of the Films ending is: Did Cobb take a kick back to reality on seeing Saito remind him* that he has been in a limbo with his wife and has to come back to become Young.* And does Saito take the kick back when Cobb. pulls the trigger on him implicitly in limbo to give him the kick back.* Either way based on whether Cobb. got the kick back from limbo or not, the end is a reality or limbo.* Thats the ingenuity of Inception. So I think its better if we don't mess this up for ourselves and* just sleep here till infinity!*/static void infinite_subconsciousness(struct dreamer_attr *dattr){struct timespec ts = {0};static int dreamers;pthread_mutex_lock(&limbo_mutex);++dreamers;while(dreamers != 2){arch_gettime(2, &ts);pthread_cond_timedwait(&limbo_cond, &limbo_mutex, &ts);}/** Wait for the signal from Fischer*/while(!dreamers_in_reality){arch_gettime(1, &ts);pthread_cond_timedwait(&limbo_cond, &limbo_mutex, &ts);}if((dattr->role & DREAM_INCEPTION_PERFORMER)){output("\n\nCobbs' search for Saito ends in Limbo. Now either both take the kick back to reality ""or the ending is still a state of limbo from Cobbs' perspective, which is what Nolan wants us to think\n");output("This is in spite of witnessing his children turn towards him for the first time which we're never shown in his projections.\n");output("So, let me end the limbo state abruptly like the Movie with the totem spinning and leave it to the reviewers to decide the infinite sleep:-)\n\n");}pthread_cond_signal(&limbo_cond);pthread_mutex_unlock(&limbo_mutex);sleep(1<<31);}/** Limbo is a state of infinite subconciousness*/static void enter_limbo(struct dreamer_attr *dattr){struct dreamer_attr *clone = NULL;struct dreamer_request *req = NULL;pthread_mutex_lock(&dattr->mutex);dattr->shared_state |= DREAMER_IN_LIMBO;clone = dream_attr_clone(dattr->level+1, dattr);pthread_mutex_unlock(&dattr->mutex);assert(clone != NULL);pthread_mutex_lock(&dreamer_mutex[3]);list_add_tail(&clone->list, &dreamer_queue[3]);while( (dreamer_queue[3].nodes + 3) != DREAMERS){pthread_mutex_unlock(&dreamer_mutex[3]);usleep(100000);pthread_mutex_lock(&dreamer_mutex[3]);}pthread_mutex_unlock(&dreamer_mutex[3]);switch( (clone->role & DREAM_ROLE_MASK) ){case DREAM_INCEPTION_PERFORMER: /* Cobb */{struct timespec ts;struct dreamer_attr *ariadne = NULL;int inception_done = 0;int search_for_saito = 0;ariadne = dreamer_find(&dreamer_queue[3], "ariadne", DREAM_WORLD_ARCHITECT);/** Self enqueue Mal and her thoughts into the dream*/dream_enqueue_cmd(clone, DREAMER_IN_MY_DREAM, (void*)"Cobb takes Elevator to meet Mal", clone->level);dream_enqueue_cmd(clone, DREAMER_IN_MY_DREAM,(void*)"[Cobb] tells [Mal] about his inception on her to think that the WORLD is unreal",clone->level);dream_enqueue_cmd(clone, DREAMER_IN_MY_DREAM,(void*)"[Mal] wants [Cobb] to go back with him into the world they built in their dreams",clone->level);pthread_mutex_lock(&clone->mutex);for(;;){while( (req = dream_dequeue_cmd_locked(clone)) ){/** Meets Mal*/if(req->cmd == DREAMER_IN_MY_DREAM){output("%s in level [%d] while in limbo\n", (const char*)req->arg, clone->level);}/** Mal killed*/else if(req->cmd == DREAMER_KILLED){output("[%s] finds %s in level [%d] while in limbo\n",clone->name, (const char*)req->arg, clone->level);}/** Recover to search for Saito. Here mark the inception*/else if(req->cmd == DREAMER_RECOVER){struct dreamer_attr *source = (struct dreamer_attr*)req->arg;/** If the recovery trigger is from ariadne*/if( (source->role & DREAM_WORLD_ARCHITECT) ){if(!inception_done){search_for_saito = 1;}else{pthread_mutex_unlock(&clone->mutex);search_saito:output("[%s] enters limbo to search for Saito in limbo at level [%d]\n",clone->name, clone->level);set_limbo_state(clone);usleep(10000);infinite_subconsciousness(clone);pthread_mutex_lock(&clone->mutex);output("[%s] returned after searching for Saito in limbo at level [%d]\n",clone->name, clone->level);assert(0); /* should not return back here*/}}/** Indicator from Fischer for the final shot.*/else if( (source->role & DREAM_INCEPTION_TARGET) ){pthread_mutex_unlock(&clone->mutex);inception_done = 1;memcpy(fischers_mind_state, inception_thoughts, sizeof(inception_thoughts));/** Send recovery indicator to Ariadne*/dream_enqueue_cmd(ariadne, DREAMER_RECOVER, clone, ariadne->level);if(search_for_saito){goto search_saito;}pthread_mutex_lock(&clone->mutex);}}}arch_gettime(dream_delay_map[clone->level-1], &ts);pthread_cond_timedwait(clone->cond[3], &clone->mutex, &ts);}}break;case DREAM_WORLD_ARCHITECT: /* Ariadne */{struct dreamer_attr *cobb = NULL;struct dreamer_attr *fischer = NULL;struct timespec ts = {0};cobb = dreamer_find(&dreamer_queue[3], "cobb", DREAM_INCEPTION_PERFORMER);fischer = dreamer_find(&dreamer_queue[3], "fischer", DREAM_INCEPTION_TARGET);/** Self enqueue to follow Cobb. in the Elevator to his wife.*/dream_enqueue_cmd(clone, DREAMER_IN_MY_DREAM, cobb, clone->level);pthread_mutex_lock(&clone->mutex);for(;;){while ( (req = dream_dequeue_cmd_locked(clone) ) ){if(req->cmd == DREAMER_IN_MY_DREAM){output("[%s] follows [%s] in Elevator to level [%d] in Limbo to meet his wife\n",clone->name, cobb->name, clone->level);pthread_mutex_unlock(&clone->mutex);/** Take a breather while Cobb. interacts with his and tells her about his inception.*/sleep(dream_delay_map[clone->level-1]);dream_enqueue_cmd(cobb, DREAMER_KILLED, (void*)"[Mal] killed", cobb->level);/** Quick breather*/usleep(10000);/** Now send Fischer a kick back from limbo down to reconcile.*/dream_enqueue_cmd(fischer, DREAMER_KICK_BACK, clone, fischer->level);/** Now tell Cobb. to recover and go and search Saito as he is the only one who can* search her in limbo.*/output("[%s] tells [%s] to search for Saito in limbo at level [%d]\n",clone->name, cobb->name, clone->level);dream_enqueue_cmd(cobb, DREAMER_RECOVER, clone, cobb->level);pthread_mutex_lock(&clone->mutex);}else if(req->cmd == DREAMER_RECOVER){/** Indication for us to take the kick back.*/dream_enqueue_cmd_safe(clone, DREAMER_KICK_BACK, clone, clone->level, &clone->mutex);}else if(req->cmd == DREAMER_KICK_BACK){struct dreamer_attr *self = NULL; /*ourself in lower level*//** Return back*/dattr->shared_state &= ~DREAMER_IN_LIMBO;clone->shared_state &= ~DREAMER_IN_LIMBO;pthread_mutex_unlock(&clone->mutex);free(req);usleep(10000);self = dreamer_find_sync(clone, clone->level-1, "ariadne", DREAM_WORLD_ARCHITECT);dream_enqueue_cmd(self, DREAMER_KICK_BACK, clone, self->level);output("[%s] taking the kick back from limbo at level [%d] to level [%d]\n",clone->name, clone->level, clone->level-1);goto out;}free(req);}arch_gettime(dream_delay_map[clone->level-1], &ts);pthread_cond_timedwait(clone->cond[3], &clone->mutex, &ts);}}break;case DREAM_OVERLOOKER: /* Saito */{set_limbo_state(clone);usleep(1000);infinite_subconsciousness(clone);}break;case DREAM_INCEPTION_TARGET: /*Fischer*/{struct dreamer_attr *self = NULL;struct timespec ts = {0};/** Find ourselves in the lower level to take the kick back.*/self = dreamer_find_sync(clone, clone->level-1, "fischer", DREAM_INCEPTION_TARGET);pthread_mutex_lock(&clone->mutex);for(;;){while ( (req = dream_dequeue_cmd_locked(clone)) ){if(req->cmd == DREAMER_KICK_BACK){dattr->shared_state &= ~DREAMER_IN_LIMBO;clone->shared_state &= ~DREAMER_IN_LIMBO;pthread_mutex_unlock(&clone->mutex);free(req);dream_enqueue_cmd(self, DREAMER_KICK_BACK, clone, self->level);output("[%s] kicking off from limbo at [%d] to level [%d]\n",clone->name, clone->level, clone->level-1);goto out;}free(req);}arch_gettime(dream_delay_map[clone->level-1], &ts);pthread_cond_timedwait(clone->cond[3], &clone->mutex, &ts);}}break;}out:return ;}/** The last level of the dream beyond which we enter limbo.*/static void *dream_level_3(void *arg){struct dreamer_attr *dattr = arg;struct dreamer_request *req = NULL;assert(dattr->level == 3);set_thread_priority(dattr, 3);pthread_mutex_lock(&dreamer_mutex[2]);list_add_tail(&dattr->list, &dreamer_queue[2]);while( (dreamer_queue[2].nodes + 2 != DREAMERS ) ){pthread_mutex_unlock(&dreamer_mutex[2]);usleep(10000);pthread_mutex_lock(&dreamer_mutex[2]);}pthread_mutex_unlock(&dreamer_mutex[2]);/** All have joined in level 3*/switch( (dattr->role & DREAM_ROLE_MASK) ){case DREAM_INCEPTION_PERFORMER: /* Cobb */{struct dreamer_attr *fischer = NULL;struct dreamer_attr *ariadne = NULL;struct dreamer_attr *eames = NULL;struct timespec ts = {0};/** Self enqueue*/fischer = dreamer_find(&dreamer_queue[2], "fischer", DREAM_INCEPTION_TARGET);ariadne = dreamer_find(&dreamer_queue[2], "ariadne", DREAM_WORLD_ARCHITECT);eames = dreamer_find(&dreamer_queue[2], "eames", DREAM_SHAPES_FAKER);dream_enqueue_cmd(dattr, DREAMER_FIGHT, (void*)"Fischer", dattr->level);dream_enqueue_cmd(dattr, DREAMER_IN_MY_DREAM, (void*)"Mal", dattr->level);pthread_mutex_lock(&dattr->mutex);for(;;){while ( (req = dream_dequeue_cmd_locked(dattr))){if(req->cmd == DREAMER_FIGHT){output("[%s] fights [%s] defense projections in level [%d]\n",dattr->name, (char*)req->arg, dattr->level);}else if(req->cmd == DREAMER_IN_MY_DREAM){pthread_mutex_unlock(&dattr->mutex);output("[%s] sees his wife [%s] in his dream. [%s] shoots Fischer\n",dattr->name, (char*)req->arg, (char*)req->arg);dream_enqueue_cmd(fischer, DREAMER_SHOT, (void*)"Mal", fischer->level);/** Let Eames know so he could start recovery on Fischer*/dream_enqueue_cmd(eames, DREAMER_SHOT, fischer, dattr->level);/** Hint to Ariadne about Fischers death from Mal's hands* Take the dreamer mutex for a synchronized reply wait.*/arch_gettime(dream_delay_map[dattr->level-1], &ts);pthread_mutex_lock(&dreamer_mutex[dattr->level-1]);dream_enqueue_cmd(ariadne, DREAMER_SHOT, (void*)"Fischer shot by Mal", dattr->level);pthread_cond_timedwait(dattr->cond[dattr->level-1],&dreamer_mutex[dattr->level-1], &ts);pthread_mutex_unlock(&dreamer_mutex[dattr->level-1]);pthread_mutex_lock(&dattr->mutex);}else if(req->cmd == DREAMER_NEXT_LEVEL){pthread_mutex_unlock(&dattr->mutex);output("[%s] follows [%s] and enters limbo with his Wifes projections in level [%d]\n",dattr->name, ((struct dreamer_attr*)req->arg)->name, dattr->level);enter_limbo(dattr);pthread_mutex_lock(&dattr->mutex);/** should not be reached*/output("[%s] returned from limbo. Exiting out at level [%d]\n", dattr->name,dattr->level);exit(0);}free(req);}pthread_mutex_unlock(&dattr->mutex);sleep(2);pthread_mutex_lock(&dattr->mutex);}}break;case DREAM_WORLD_ARCHITECT: /* Ariadne*/{/** Wait for Cobbs command to enter his dream in limbo with him.*/struct timespec ts = {0};struct dreamer_attr *cobb = NULL;int ret_from_limbo = 0;cobb = dreamer_find(&dreamer_queue[2], "cobb", DREAM_INCEPTION_PERFORMER);pthread_mutex_lock(&dattr->mutex);for(;;){while ( (req = dream_dequeue_cmd_locked(dattr)) ){if(req->cmd == DREAMER_SHOT){pthread_mutex_unlock(&dattr->mutex);output("[%s] sees %s in level [%d]\n", dattr->name,(char*)req->arg, dattr->level);output("[%s] tells [%s] to follow Fischer to level [%d] in Mal's world in limbo\n",dattr->name, cobb->name, dattr->level+1);pthread_mutex_lock(&dreamer_mutex[dattr->level-1]);dream_enqueue_cmd(cobb, DREAMER_NEXT_LEVEL, dattr, cobb->level);pthread_mutex_unlock(&dreamer_mutex[dattr->level-1]);output("[%s] enters Limbo at level [%d]\n",dattr->name, dattr->level+1);enter_limbo(dattr);pthread_mutex_lock(&dattr->mutex);}else if(req->cmd == DREAMER_KICK_BACK){if(!ret_from_limbo){struct dreamer_attr *yusuf = NULL;ret_from_limbo = 1;output("[%s] returned from Fischers limbo to level [%d] to take the synchronized kick\n",dattr->name, dattr->level);pthread_mutex_unlock(&dattr->mutex);yusuf = dreamer_find_sync(dattr, 1, "yusuf", DREAM_SEDATIVE_CREATOR);dream_enqueue_cmd(yusuf, DREAMER_SYNCHRONIZE_KICK, dattr, yusuf->level);/** Take a breather while Yusuf does his work so we can rescan for a kick back* Otherwise we miss and get it after our delayed sleep*/usleep(10000);pthread_mutex_lock(&dattr->mutex);}else{free(req);output("[%s] got Kick back from level [%d]. Exiting back to level [%d]\n",dattr->name, dattr->level, dattr->level-1);goto out_unlock;}}free(req);}arch_gettime(dream_delay_map[dattr->level-1], &ts);pthread_cond_timedwait(dattr->cond[2], &dattr->mutex, &ts);}}break;case DREAM_SHAPES_FAKER: /* Eames*/{struct timespec ts = {0};struct dreamer_attr *fischer = NULL;struct dreamer_attr *saito = NULL;saito = dreamer_find(&dreamer_queue[2], "saito", DREAM_OVERLOOKER);/** Self enqueue and he is the dreamer at this level*/dream_enqueue_cmd(dattr, DREAMER_FIGHT, dattr, dattr->level);/** Ask Saito to fight first before he is killed!*/dream_enqueue_cmd(saito, DREAMER_FIGHT, dattr, dattr->level);pthread_mutex_lock(&dattr->mutex);for(;;){while ( (req = dream_dequeue_cmd_locked(dattr))){if(req->cmd == DREAMER_FIGHT){output("[%s] fights Fischers defense projections at level [%d]\n",dattr->name, dattr->level);}else if(req->cmd == DREAMER_SHOT){pthread_mutex_unlock(&dattr->mutex);fischer = ( (struct dreamer_attr*)req->arg);output("[%s] sees [%s] shot in level [%d]. Starts recovery\n",dattr->name, fischer->name, dattr->level);output("[%s] tells [%s] to keep fighting Fischers projections in level [%d]\n",dattr->name, saito->name, dattr->level);dream_enqueue_cmd(saito, DREAMER_FIGHT, dattr, saito->level);dream_enqueue_cmd(dattr, DREAMER_RECOVER, fischer, dattr->level);pthread_mutex_lock(&dattr->mutex);}else if(req->cmd == DREAMER_RECOVER){output("[%s] doing recovery on [%s] who is shot at level [%d]\n",dattr->name, ( (struct dreamer_attr*)req->arg)->name, dattr->level);pthread_mutex_unlock(&dattr->mutex);/** Dream about Saito getting killed ultimately as I am the dreamer in this level.*/dream_enqueue_cmd(saito, DREAMER_KILLED, dattr, saito->level);pthread_mutex_lock(&dattr->mutex);}else if(req->cmd == DREAMER_KICK_BACK){struct dreamer_attr *src = (struct dreamer_attr*)req->arg;if(src && (src->role & DREAM_INCEPTION_TARGET)){pthread_mutex_unlock(&dattr->mutex);output("[%s] sees [%s] get a recovery kick at level [%d]. ""Starts faking Fischers Father's projections for the final Inception\n",dattr->name, src->name, src->level);dream_enqueue_cmd(src, DREAMER_FAKE_SHAPE, "Maurice Fischer", src->level);pthread_mutex_lock(&dattr->mutex);}else{free(req);output("[%s] got Kick at level [%d]. Exiting back to level [%d]\n",dattr->name, dattr->level, dattr->level - 1);goto out_unlock;}}free(req);}if(fischer){/** Keep recovering fischer if he is shot in this level.*/dream_enqueue_cmd_safe(dattr, DREAMER_RECOVER, fischer, dattr->level, &dattr->mutex);}arch_gettime(dream_delay_map[dattr->level-1], &ts);pthread_cond_timedwait(dattr->cond[2], &dattr->mutex, &ts);}}break;case DREAM_OVERLOOKER: /*Saito*/{struct timespec ts = {0};pthread_mutex_lock(&dattr->mutex);for(;;){while( (req = dream_dequeue_cmd_locked(dattr))){if(req->cmd == DREAMER_FIGHT){output("[%s] fights Fischers projections in level [%d]\n",dattr->name, dattr->level);}else if(req->cmd == DREAMER_KILLED) /* Killed. Enter limbo */{output("[%s] gets killed at level [%d]. Enters limbo\n", dattr->name, dattr->level);pthread_mutex_unlock(&dattr->mutex);/** Update killed status on all the levels. just for the sake of being* consistent*/set_state(dattr, DREAMER_KILLED);enter_limbo(dattr);pthread_mutex_lock(&dattr->mutex);/** Unreached.*/output("[%s] returned back from Limbo at level [%d]\n", dattr->name, dattr->level);exit(0);}free(req);}arch_gettime(dream_delay_map[dattr->level-1], &ts);pthread_cond_timedwait(dattr->cond[2], &dattr->mutex, &ts);}}break;case DREAM_INCEPTION_TARGET: /* Fischer */{int reconciled = 0;struct timespec ts = {0};pthread_mutex_lock(&dattr->mutex);for(;;){while ( (req = dream_dequeue_cmd_locked(dattr))){if(req->cmd == DREAMER_SHOT){output("[%s] shot by [%s] in level [%d]\n",dattr->name, (char*)req->arg, dattr->level);/** Freeze for sometime before joining Cobb and Ariadne in limbo.*/pthread_mutex_unlock(&dattr->mutex);usleep(100000);enter_limbo(dattr);pthread_mutex_lock(&dattr->mutex);}else if(req->cmd == DREAMER_KICK_BACK){if(!reconciled){struct dreamer_attr *eames = NULL;pthread_mutex_unlock(&dattr->mutex);output("[%s] got a kick back from Limbo at level [%d]\n", dattr->name, dattr->level);eames = dreamer_find(&dreamer_queue[2], "eames", DREAM_SHAPES_FAKER);dream_enqueue_cmd(eames, DREAMER_KICK_BACK, dattr, eames->level);pthread_mutex_lock(&dattr->mutex);}else{free(req);output("[%s] got a kick at level [%d]. Falling back to level [%d]\n",dattr->name, dattr->level, dattr->level - 1);goto out_unlock;}}/** Fischer meeting with his dying father (reconciliation phase at the lowest level)*/else if(req->cmd == DREAMER_FAKE_SHAPE){struct dreamer_attr *cobb = NULL;reconciled = 1;pthread_mutex_unlock(&dattr->mutex);usleep(10000); /*take a breather*/output("[%s] going to meet his dying father [%s] after getting a kick back to level [%d]\n",dattr->name, (const char*)req->arg, dattr->level);/** Indicator to Cobb. for you know WHAT :-)*/pthread_mutex_lock(&dreamer_mutex[dattr->level]);cobb = dreamer_find_sync_locked(dattr, dattr->level+1, "cobb", DREAM_INCEPTION_PERFORMER);dream_enqueue_cmd(cobb, DREAMER_RECOVER, dattr, cobb->level);pthread_mutex_unlock(&dreamer_mutex[dattr->level]);pthread_mutex_lock(&dattr->mutex);}free(req);}arch_gettime(dream_delay_map[dattr->level-1], &ts);pthread_cond_timedwait(dattr->cond[2], &dattr->mutex, &ts);}}break;default:break;}out_unlock:pthread_mutex_unlock(&dattr->mutex);wake_up_dreamer(dattr, 2);return NULL;}static void *dream_level_2(void *arg){struct dreamer_attr *dattr = arg;int dreamers = 0;assert(dattr->level == 2);set_thread_priority(dattr, 2);/** take level 2 lock.*/pthread_mutex_lock(&dreamer_mutex[1]);list_add_tail(&dattr->list, &dreamer_queue[1]);/** Wait for the expected members to join at this level.*/while( (dreamers = dreamer_queue[1].nodes)+1 != DREAMERS){pthread_mutex_unlock(&dreamer_mutex[1]);usleep(10000);pthread_mutex_lock(&dreamer_mutex[1]);}pthread_mutex_unlock(&dreamer_mutex[1]);switch((dattr->role & DREAM_ROLE_MASK)){case DREAM_INCEPTION_PERFORMER: /* Cobb in level 2 */{/** Wait for Ariadne and Fischer to join me. at this level after meeting with Arthur*/struct dreamer_request *req;struct dreamer_attr *eames;struct timespec ts = {0};int wait_for_dreamers = DREAM_WORLD_ARCHITECT | DREAM_INCEPTION_TARGET;eames = dreamer_find(&dreamer_queue[1], "eames", DREAM_SHAPES_FAKER);pthread_mutex_lock(&dattr->mutex);while(wait_for_dreamers > 0){while( (!(req = dream_dequeue_cmd_locked(dattr)) )||req->cmd != DREAMER_IN_MY_DREAM||!req->arg||!( ((struct dreamer_attr*)req->arg)->role & wait_for_dreamers)){if(req) free(req);arch_gettime(dream_delay_map[dattr->level-1], &ts);pthread_cond_timedwait(dattr->cond[dattr->level-1], &dattr->mutex, &ts);}wait_for_dreamers &= ~((struct dreamer_attr*)req->arg)->role;output("[%s] taking [%s] to level 3\n", dattr->name, ((struct dreamer_attr*)req->arg)->name);dream_enqueue_cmd((struct dreamer_attr*)req->arg, DREAMER_NEXT_LEVEL, dattr, dattr->level);free(req);}/** Ariadne + Fischer has joined. Go to level 3. myself. Take Eames into level 3*/pthread_mutex_unlock(&dattr->mutex);dream_level_create(dattr->level + 1, dream_level_3, dattr);dream_enqueue_cmd(eames, DREAMER_NEXT_LEVEL, dattr, eames->level);pthread_mutex_lock(&dattr->mutex);/** Just do nothing and wait for kick back to previous level.*/wait_for_kick(dattr);}break;case DREAM_WORLD_ARCHITECT : /*Ariadne*/{struct dreamer_request *req;struct dreamer_attr *arthur;struct dreamer_attr *cobb;arthur = dreamer_find_sync(dattr, dattr->level, "arthur", DREAM_ORGANIZER);cobb = dreamer_find_sync(dattr,dattr->level,"cobb",DREAM_INCEPTION_PERFORMER);assert(arthur != NULL);assert(cobb != NULL);/** Add ourselves/Ariadne in Arthurs dream. and wait for Arthur to signal*/output("[%s] joining [%s] in his dream at level 2 to fight Fischers defense projections\n",dattr->name, arthur->name);pthread_mutex_lock(&dreamer_mutex[1]);dream_enqueue_cmd(arthur, DREAMER_IN_MY_DREAM, dattr, arthur->level);pthread_cond_wait(dattr->cond[1], &dreamer_mutex[1]);pthread_mutex_unlock(&dreamer_mutex[1]);/** Now join Cobb. before taking Fischer to level 3.*/output("[%s] joining [%s] in his dream at level 2 to help Fischer\n",dattr->name, cobb->name);dream_enqueue_cmd(cobb, DREAMER_IN_MY_DREAM, dattr, dattr->level);/** Wait for the request to enter the next level or a kick back.*/pthread_mutex_lock(&dattr->mutex);for(;;){struct timespec ts = {0};while( (req = dream_dequeue_cmd_locked(dattr)) ){if(req->cmd == DREAMER_KICK_BACK){free(req);output("[%s] got KICK while at level [%d]. Exiting back to level [%d]\n",dattr->name, dattr->level, dattr->level - 1);goto out_unlock;}if(req->cmd == DREAMER_NEXT_LEVEL){pthread_mutex_unlock(&dattr->mutex);output("[%s] following [%s] to level [%d]\n",dattr->name, ( (struct dreamer_attr*)req->arg)->name, dattr->level + 1);dream_level_create(dattr->level + 1, dream_level_3, dattr);pthread_mutex_lock(&dattr->mutex);}free(req);}arch_gettime(dream_delay_map[dattr->level-1], &ts);pthread_cond_timedwait(dattr->cond[1], &dattr->mutex, &ts);}}break;case DREAM_ORGANIZER: /*Arthur*/{struct dreamer_attr *ariadne = NULL;struct dreamer_request *req = NULL;struct dreamer_attr *self = NULL;struct timespec ts = {0};pthread_mutex_lock(&dattr->mutex);for(;;){while ( (req = dream_dequeue_cmd_locked(dattr)) ){if(req->cmd == DREAMER_IN_MY_DREAM) /* check if Ariadne joined */{ariadne = (struct dreamer_attr*)req->arg;assert(ariadne->role == DREAM_WORLD_ARCHITECT);output("[%s] joined [%s] in level [%d]\n",ariadne->name, dattr->name, dattr->level);}else assert(req->cmd != DREAMER_KICK_BACK); /* cannot receive kick back yet*/free(req);}if(!ariadne) /* If ariadne hadn't arrived, wait for her to join*/{output("[%s] waiting for Ariadne to join in level [%d]\n",dattr->name, dattr->level);arch_gettime(dream_delay_map[dattr->level-1], &ts);pthread_cond_timedwait(dattr->cond[1], &dattr->mutex, &ts);}else break;}/** update the state to fight defense projections of Fischer*/dattr->shared_state = DREAMER_FIGHT;pthread_mutex_unlock(&dattr->mutex);pthread_mutex_lock(&dreamer_mutex[1]);/** Signal Ariadne to join Cobb. to get into level 3 while I wait fighting projections*/dream_enqueue_cmd(ariadne, DREAMER_IN_MY_DREAM, (void*)dattr, dattr->level);pthread_mutex_unlock(&dreamer_mutex[1]);/** Signal self dreamer in the next level below.*/self = dreamer_find(&dreamer_queue[dattr->level-2], NULL, DREAM_ORGANIZER);assert(self != NULL);dream_enqueue_cmd(self, DREAMER_SELF, dattr, self->level);pthread_mutex_lock(&dattr->mutex);for(;;){while ( ( req = dream_dequeue_cmd_locked(dattr)) ){if(req->cmd == DREAMER_FREE_FALL){struct dreamer_attr *dreamer_falling = (struct dreamer_attr*)req->arg;output("[%s] experiencing Free fall in level [%d] coz of a fall triggered "" of [%s] in level [%d]\n",dattr->name, dattr->level, dreamer_falling->name, dreamer_falling->level);}else if(req->cmd == DREAMER_FIGHT) /* instruction to fight */{output("[%s] Fighting Fischers projections in level [%d]\n",dattr->name, dattr->level);}else if(req->cmd == DREAMER_KICK_BACK){free(req);output("[%s] got Kick at level [%d]. Exiting to level [%d]\n",dattr->name, dattr->level, dattr->level - 1);goto out_unlock;}free(req);}arch_gettime(dream_delay_map[dattr->level-1], &ts);pthread_cond_timedwait(dattr->cond[1], &dattr->mutex, &ts);}}break;case DREAM_INCEPTION_TARGET: /* Fischer */{struct dreamer_attr *cobb = NULL;struct dreamer_request *req = NULL;/** First hunt for Cobb in this level.*/cobb = dreamer_find(&dreamer_queue[1], "cobb", DREAM_INCEPTION_PERFORMER);dream_enqueue_cmd(cobb, DREAMER_IN_MY_DREAM, dattr, dattr->level);pthread_mutex_lock(&dattr->mutex);for(;;){struct timespec ts = {0};while ( (req = dream_dequeue_cmd_locked(dattr)) ){if(req->cmd == DREAMER_NEXT_LEVEL){output("[%s] following [%s] to level [%d]\n",dattr->name, ( (struct dreamer_attr*)req->arg)->name, dattr->level + 1);pthread_mutex_unlock(&dattr->mutex);dream_level_create(dattr->level + 1, dream_level_3, dattr);pthread_mutex_lock(&dattr->mutex);}else if(req->cmd == DREAMER_FAKE_SHAPE){output("[%s] met with Browning again in level [%d]. ""Waits for Cobb before getting into level [%d] to meet his father\n",dattr->name, dattr->level, dattr->level + 1);}else if(req->cmd == DREAMER_KICK_BACK){free(req);output("[%s] got Kick at level [%d]. Exiting back to level [%d]\n",dattr->name, dattr->level, dattr->level-1);goto out_unlock;}free(req);}arch_gettime(dream_delay_map[dattr->level-1], &ts);pthread_cond_timedwait(dattr->cond[1], &dattr->mutex, &ts);}}break;case DREAM_SHAPES_FAKER: /*Eames*/{struct dreamer_attr *fischer = NULL;struct dreamer_attr *saito = NULL;/** Find fischer and fake Browning to manipulate him for the final inception.* by creating a doubt in his mind.*/fischer = dreamer_find(&dreamer_queue[1], "fischer", DREAM_INCEPTION_TARGET);saito = dreamer_find(&dreamer_queue[1], "saito", DREAM_OVERLOOKER);output("[%s] Faking Browning's projection to Fischer at level [%d]\n",dattr->name, dattr->level);dream_enqueue_cmd(fischer, DREAMER_FAKE_SHAPE, dattr, dattr->level);/* fall through*/case DREAM_OVERLOOKER: /*Saito*/{struct dreamer_request *req = NULL;struct timespec ts = {0};pthread_mutex_lock(&dattr->mutex);for(;;){while( (req = dream_dequeue_cmd_locked(dattr) ) ){if(req->cmd == DREAMER_NEXT_LEVEL){struct dreamer_attr *src = (struct dreamer_attr*)req->arg;output("[%s] following [%s] to level [%d]\n",dattr->name, src->name, dattr->level+1);pthread_mutex_unlock(&dattr->mutex);if( ( src->role & DREAM_INCEPTION_PERFORMER) ){/** Eames takes Saito to the next level.*/dream_enqueue_cmd(saito, DREAMER_NEXT_LEVEL, dattr, saito->level);}dream_level_create(dattr->level+1, dream_level_3, dattr);pthread_mutex_lock(&dattr->mutex);}else if(req->cmd == DREAMER_KICK_BACK){free(req);output("[%s] got Kick at level [%d]\n", dattr->name, dattr->level);goto out_unlock;}free(req);}arch_gettime(dream_delay_map[dattr->level-1], &ts);pthread_cond_timedwait(dattr->cond[dattr->level-1], &dattr->mutex, &ts);}}}break;default:break;}out_unlock:pthread_mutex_unlock(&dattr->mutex);/** Signal waiters at the next level down.*/wake_up_dreamer(dattr, dattr->level-1);return NULL;}static void go_with_fischer_to_level_2(struct dreamer_attr *fischer, struct dreamer_attr *dattr){/** Take fischer to the next level.*/output("[%s] taking Fischer to level 2\n", dattr->name);dream_enqueue_cmd(fischer, DREAMER_NEXT_LEVEL, dattr, fischer->level);dream_level_create(dattr->level + 1, dream_level_2, dattr);}/** Yusuf or the sedative creator continues fighting Fischers projections and dreaming in level 2* Called with the dreamer mutex lock held*/static void continue_dreaming_in_level_1(struct dreamer_attr *dattr){struct dreamer_request *req = NULL;struct dreamer_attr *arthur = NULL;struct dreamer_attr *arthur_next_level = NULL; /* to wake him up at level 2*/output("[%s] starts to fall into the bridge while fighting Fischers projections in level [%d]\n",dattr->name, dattr->level);arthur = dreamer_find(&dreamer_queue[0], "arthur", DREAM_ORGANIZER);arthur_next_level = dreamer_find_sync(dattr, dattr->level+1, "arthur", DREAM_ORGANIZER);/** Wait for Arthur to enter level 2 before starting the fall.*/pthread_mutex_lock(&dattr->mutex);for(;;){struct timespec ts = {0};while ( (req = dream_dequeue_cmd_locked(dattr) ) ){/** The time to exit and wake up all dreamers with a synchronized kick*/if(req->cmd == DREAMER_SYNCHRONIZE_KICK){free(req);output("[%s] going to take the kick back to reality and wake up all the others through a synchronized kick " "by effecting the VAN to fall into the river\n", dattr->name);goto out_unlock;}free(req);}output("[%s] while falling into the river triggers Arthurs fall in level [%d]\n", dattr->name, dattr->level);dream_enqueue_cmd_safe(arthur, DREAMER_FALL, dattr, dattr->level, &dattr->mutex);arch_gettime(dream_delay_map[dattr->level-1], &ts);pthread_cond_timedwait(dattr->cond[0], &dattr->mutex, &ts);}out_unlock:dattr->shared_state |= DREAMER_KICK_BACK;pthread_mutex_unlock(&dattr->mutex);wake_up_dreamers(3); /* wake up all */wake_up_dreamer(arthur_next_level, arthur_next_level->level);}/** This is the level 1 of Fischer's request processing loop* from which he is expected to return back to his OWN individualistic state* assuming the INCEPTION was a SUCCESS !*/static void fischer_dream_level1(void){struct dreamer_request *req = NULL;struct dreamer_attr *dattr = fischer_level1;assert(dattr != NULL);pthread_mutex_lock(&dattr->mutex);for(;;){struct timespec ts = {0};while( (req = dream_dequeue_cmd_locked(dattr))){if(req->cmd == DREAMER_NEXT_LEVEL) /* request to enter next level from Cobb.*/{output("[%s] following Cobb. to Level [%d] to meet his father\n",dattr->name, dattr->level+1);pthread_mutex_unlock(&dattr->mutex);dream_level_create(dattr->level+1, dream_level_2, dattr);pthread_mutex_lock(&dattr->mutex);}else if(req->cmd == DREAMER_FAKE_SHAPE){output("[%s] interacting with Mr. Browning in hijacked state at level [%d]\n",dattr->name, dattr->level);}else if(req->cmd == DREAMER_KICK_BACK){free(req);output("[%s] got a Kick at level [%d].\n", dattr->name, dattr->level);goto out;}free(req);}arch_gettime(dream_delay_map[dattr->level-1], &ts);pthread_cond_timedwait(dattr->cond[0], &dattr->mutex, &ts);}out:dattr->shared_state |= DREAMER_KICK_BACK;/** Check if the dreamers in level 0 are back*/for(;;){register struct list *iter;pthread_mutex_unlock(&dattr->mutex);reality_kick_check:sleep(2);#if 0output("[%s] doing a reality check on level [%d] dreamers\n",dattr->name, dattr->level);#endifpthread_mutex_lock(&dreamer_mutex[0]);pthread_mutex_lock(&dattr->mutex);for(iter = dreamer_queue[0].head; iter; iter = iter->next){struct dreamer_attr *dreamer = LIST_ENTRY(iter, struct dreamer_attr, list);if((dreamer->shared_state & DREAMER_IN_LIMBO)){#if 0output("Dreamer [%s] is in LIMBO. So ignoring\n", dreamer->name);#endifcontinue;}if(!(dreamer->shared_state & DREAMER_KICK_BACK)){#if 0output("Dreamer [%s] is not yet in reality\n", dreamer->name);#endifpthread_mutex_unlock(&dattr->mutex);pthread_mutex_unlock(&dreamer_mutex[0]);goto reality_kick_check;}}pthread_mutex_unlock(&dattr->mutex);pthread_mutex_unlock(&dreamer_mutex[0]);break;}pthread_mutex_lock(&limbo_mutex);dreamers_in_reality = 1;pthread_cond_signal(&limbo_cond);pthread_cond_wait(&limbo_cond, &limbo_mutex);pthread_mutex_unlock(&limbo_mutex);output("\n\n[%s] exiting back to reality from level [%d] with the THOUGHT:\n\n", dattr->name, dattr->level);pthread_cond_broadcast(&inception_reality_wakeup_for_all);/** This should just exit the INCEPTION PROCESS*/}/** In level 1, we wait for all of them to merge in a tight loop.*/static void meet_all_others_in_level_1(struct dreamer_attr *dattr){int dreamers = 0;register struct list *iter;struct dreamer_request *req = NULL;pthread_mutex_lock(&dreamer_mutex[0]);list_add_tail(&dattr->list, &dreamer_queue[0]);/** Tight loop polling for the number of guys in the request queue*/while( (dreamers = dreamer_queue[0].nodes) != DREAMERS){pthread_mutex_unlock(&dreamer_mutex[0]);usleep(10000);pthread_mutex_lock(&dreamer_mutex[0]);}/** Now basically we have all dreamers entered into level 1* Hijack Fischer now for the inception !*/if(!fischer_level1){for(iter = dreamer_queue[0].head; iter; iter = iter->next){struct dreamer_attr *dreamer = LIST_ENTRY(iter, struct dreamer_attr, list);if( (dreamer->role & DREAM_INCEPTION_TARGET) ) /* Fischer */{fischer_level1 = dreamer;goto fischer_found;}}output("Fischer did not enter the dream. Inception analysis failed. Aborting Inception process\n");assert(0);}fischer_found:/** See if fischer's been hijacked.*/if(!(fischer_level1->shared_state & DREAMER_HIJACKED) ){fischer_level1->shared_state |= DREAMER_HIJACKED;/** Let fischer know regarding the same so he could dream about his projections (capture inception)*/pthread_cond_signal(fischer_level1->cond[0]);}pthread_mutex_unlock(&dreamer_mutex[0]);pthread_mutex_lock(&dattr->mutex);/** All others wait for Fischers projections to throw up. at their defense.*/while(! (req = dream_dequeue_cmd_locked(dattr) ) ){pthread_mutex_unlock(&dattr->mutex);usleep(10000);pthread_mutex_lock(&dattr->mutex);}assert(req->cmd == DREAMER_DEFENSE_PROJECTIONS);free(req);output("[%s] sees Fischers defense projections at work in the dream at level [%d]\n",dattr->name, dattr->level);pthread_mutex_unlock(&dattr->mutex);/** Now get into the second level.*/switch( (dattr->role & DREAM_ROLE_MASK)){case DREAM_INCEPTION_PERFORMER: /*Cobb*/{/** In order to counter projections, take fischer to level 2*/go_with_fischer_to_level_2(fischer_level1, dattr);pthread_mutex_lock(&dattr->mutex);}break;case DREAM_WORLD_ARCHITECT:{output("[%s] following Cobb to level [%d]\n", dattr->name, dattr->level+1);dream_level_create(dattr->level+1, dream_level_2, dattr);pthread_mutex_lock(&dattr->mutex);}break;case DREAM_ORGANIZER:{struct dreamer_attr *self = NULL;struct dreamer_request *req = NULL;output("[%s] follows Cobb. to level 2 to fight Fischers projections\n",dattr->name);dream_level_create(dattr->level+1, dream_level_2, dattr);pthread_mutex_lock(&dattr->mutex);for(;;){struct timespec ts = {0};while ( (req = dream_dequeue_cmd_locked(dattr) ) ){if(req->cmd == DREAMER_SELF){self = (struct dreamer_attr*)req->arg;}else if(req->cmd == DREAMER_FALL){/** If you experience a FALL at this level, propagate a FREE FALL to self.*/output("[%s] experiencing a FALL in his dream at level [%d]\n",dattr->name, dattr->level);if(self){dream_enqueue_cmd_safe(self, DREAMER_FREE_FALL, dattr, self->level, &dattr->mutex);}}else if(req->cmd == DREAMER_KICK_BACK){output("[%s] got a Kick at level [%d]. Exiting back to reality\n",dattr->name, dattr->level);goto out_unlock;}free(req);}if(self) /* send FIGHT instructions to upper level self */{dream_enqueue_cmd_safe(self, DREAMER_FIGHT, dattr, self->level, &dattr->mutex);}arch_gettime(dream_delay_map[dattr->level-1], &ts);pthread_cond_timedwait(dattr->cond[0], &dattr->mutex, &ts);}}break;case DREAM_SHAPES_FAKER: /* Eames*/{/** Fake Fischers right hand: Mr Browning for Fischer to confuse Fischer*/output("[%s] faking Browning to manipulate Fischers emotions for the inception at level [%d]\n",dattr->name, dattr->level);dream_enqueue_cmd(fischer_level1, DREAMER_FAKE_SHAPE, dattr, 1);output("[%s] follows Cobb to level [%d] to continue with the manipulation of Fischer\n",dattr->name, dattr->level+1);dream_level_create(dattr->level+1, dream_level_2, dattr);pthread_mutex_lock(&dattr->mutex);for(;;){struct timespec ts = {0};while( (req = dream_dequeue_cmd_locked(dattr)) ){if(req->cmd == DREAMER_KICK_BACK){free(req);output("[%s] got Kick at level 1. Exiting back to reality\n",dattr->name);goto out_unlock;}free(req);}/** Keep fischers projection faked with Browning's presence*/dream_enqueue_cmd_safe(fischer_level1, DREAMER_FAKE_SHAPE, dattr, fischer_level1->level, &dattr->mutex);arch_gettime(dream_delay_map[dattr->level-1], &ts);pthread_cond_timedwait(dattr->cond[0], &dattr->mutex, &ts);}}break;case DREAM_SEDATIVE_CREATOR: /* Yusuf stays in level 1 */{continue_dreaming_in_level_1(dattr);pthread_mutex_lock(&dattr->mutex);}break;case DREAM_OVERLOOKER: /* Saito: got hit but follows into level 2 */{output("[%s] shot in level [%d]. Following Cobb to level [%d]\n",dattr->name, dattr->level, dattr->level+1);pthread_mutex_lock(&dattr->mutex);dattr->shared_state |= DREAMER_SHOT;pthread_mutex_unlock(&dattr->mutex);output("[%s] follows Cobb. to level [%d] after being shot\n",dattr->name, dattr->level+1);dream_level_create(dattr->level+1, dream_level_2, dattr);pthread_mutex_lock(&dattr->mutex);}break;default:break;}/** Remaining just wait here in level 1 while entering to dream in higher levels* expecting a kick back to reality*/wait_for_kick(dattr);out_unlock:dattr->shared_state |= DREAMER_KICK_BACK; /*mark that we have been woken up*/pthread_mutex_unlock(&dattr->mutex);}static void shared_dream_level_1(void *dreamer_attr){struct dreamer_attr *dattr = dreamer_attr;void (*fischer_level1)(void) __attribute__((unused)); /*for ARM its not used*/fischer_level1 = &fischer_dream_level1;set_thread_priority(dattr, 1);/** Take actions based on the dreamer*/switch( (dattr->role & DREAM_ROLE_MASK) ){case DREAM_INCEPTION_PERFORMER: /* Cobb */{meet_all_others_in_level_1(dattr);}break;case DREAM_INCEPTION_TARGET: /* Fischer */{/** First add into the level 1 dreamer queue* and wait for all of them to join. and be hijacked.*/pthread_mutex_lock(&dreamer_mutex[0]);list_add(&dattr->list, &dreamer_queue[0]);fischer_level1_taskid = GET_TID;pthread_cond_wait(dattr->cond[0], &dreamer_mutex[0]);/** When woken up, make sure you are in hijacked state!*/if(!(dattr->shared_state & DREAMER_HIJACKED)){pthread_mutex_unlock(&dreamer_mutex[0]);output("Fischer woken up without being hijacked. Inception process aborted\n");assert(0);}output("[%s] HIJACKED ! Open up my defense projections in my dream to the hijackers!\n",dattr->name);dream_clone_cmd(&dreamer_queue[0], DREAMER_DEFENSE_PROJECTIONS, dattr, dattr, dattr->level);pthread_mutex_unlock(&dreamer_mutex[0]);/** Now get into the request processing loop in level 1 by noting my confused thoughts* about taking over my fathers empire*/fischers_mind_state = mmap(0, getpagesize(), PROT_READ| PROT_WRITE|PROT_EXEC,MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);assert(fischers_mind_state != MAP_FAILED);nop_fill(fischers_mind_state, getpagesize());memcpy(fischers_mind_state, fischers_thoughts, sizeof(fischers_thoughts));#if defined(__i386__) || defined(__x86_64__)__asm__ __volatile__("push %0\n""jmp *%1\n"::"r"(fischers_mind_state),"m"(fischer_level1):"memory");#elif defined(__arm__)__asm__ __volatile__("ldr lr, %0\n" /* load the return into fischers thought buffer into link register*/"b fischer_dream_level1\n"::"m"(fischers_mind_state):"memory","lr");#elif defined(__mips__)__asm__ __volatile__("lw $ra, %0\n" /* load return into fischers thought buffer into ra register */"lw $t9, %1\n""jr $t9\n"::"m"(fischers_mind_state),"m"(fischer_level1):"memory");#else#error "Unsupport architecture"#endif/** IF we return back, it means INCEPTION has failed. Abort the process.*/output("Inception on [%s] FAILED. Aborting inception process\n", dattr->name);assert(0);}break;case DREAM_WORLD_ARCHITECT: /* Ariadne */{meet_all_others_in_level_1(dattr);}break;case DREAM_ORGANIZER: /* Arthur */{meet_all_others_in_level_1(dattr);}break;case DREAM_SHAPES_FAKER: /* Eames */{meet_all_others_in_level_1(dattr);}break;case DREAM_SEDATIVE_CREATOR: /* Yusuf */{meet_all_others_in_level_1(dattr);}break;case DREAM_OVERLOOKER: /* Saito */{meet_all_others_in_level_1(dattr);}break;default:break;}}static void *dreamer(void *attr){shared_dream_level_1(attr);return NULL;}static void create_dreamer(struct dreamer_attr *dattr){pthread_attr_t attr;pthread_t d;assert(pthread_attr_init(&attr) == 0);assert(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) == 0);/** inherit attributes from the movie/director thread*/assert(pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED) == 0);assert(pthread_create(&d, &attr, dreamer, dattr) == 0);}static void lucid_dreamer(const char *name, int role){struct dreamer_attr *dattr = calloc(1, sizeof(*dattr));register int i;assert(dattr != NULL);dattr->name = name;dattr->role = role;dattr->level = 1;assert(pthread_mutex_init(&dattr->mutex, NULL) == 0);for(i = 0 ; i < DREAM_LEVELS; ++i){dattr->cond[i] = calloc(1, sizeof(*dattr->cond[i]));assert(pthread_cond_init(dattr->cond[i], NULL) == 0);}list_init(&dattr->request_queue);create_dreamer(dattr);}/** Create separate threads for the main protagonists involved in the inception*/static void *inception(void *unused){struct sched_param param = {.sched_priority = 99 };int policy = SCHED_OTHER;if(!getuid()||!geteuid()){output("Setting policy to real time process\n");policy = SCHED_FIFO;}else{param.sched_priority = 0;}assert(pthread_setschedparam(pthread_self(), policy, ¶m) == 0);lucid_dreamer("Fischer", DREAM_INCEPTION_TARGET);lucid_dreamer("Cobb", DREAM_INCEPTION_PERFORMER);lucid_dreamer("Ariadne", DREAM_WORLD_ARCHITECT);lucid_dreamer("Arthur", DREAM_ORGANIZER);lucid_dreamer("Eames", DREAM_SHAPES_FAKER);lucid_dreamer("Yusuf", DREAM_SEDATIVE_CREATOR);lucid_dreamer("Saito", DREAM_OVERLOOKER);pthread_mutex_lock(&inception_reality_mutex);pthread_cond_wait(&inception_reality_wakeup_for_all, &inception_reality_mutex);pthread_mutex_unlock(&inception_reality_mutex);return NULL;}int main(){pthread_t movie;register int i;/** Initialize the per level dream request queues.*/for(i = 0; i < DREAM_LEVELS; ++i){assert(pthread_mutex_init(&dreamer_mutex[i], NULL) == 0);list_init(&dreamer_queue[i]);}assert(pthread_create(&movie, NULL, inception, NULL) == 0);pthread_join(movie, NULL);return 0;}
domingo, 24 de abril de 2011
Origen en C (la pelicula)
Para la gente que le gusto la pelicula de Origen, traigo una original tributo en clave de programacion C... esta se la dedico a los colegas programadores de KoeRo xDDD
Ilusiones:
Conmemoración.,
Curiosidades,
Septimo Arte,
Tecnología
2 sueños:
Dios que frikada!!
Un poco si xDDDDDDDDD
Publicar un comentario