Mostrando entradas con la etiqueta Curiosidades. Mostrar todas las entradas
Mostrando entradas con la etiqueta Curiosidades. Mostrar todas las entradas

jueves, 16 de octubre de 2014

Te Ex-Quiero

Te ex-quiero.

te ex-quiero
Todos tenemos un ex, o dos, o varios. Personas que han formado parte de nuestras vidas y que en más o en menos tiempo y que con más o con menos sentimientos, marcaron un antes y un después en nuestra historia.
Ex, una palabra indecorosa, antiestética, que casi siempre viene acompañada de dolor de estómago, de recuerdos repletos de nostalgia, confusión, rencor y a veces de odio. ¿Por qué? ¿Por qué en la mayoría de los casos, después de haber roto una relación sentimental ya no volvemos a tener contacto, ni una relación cordial o de amistad, con una persona con la que hemos compartido tanto? ¿No es triste? Es tristísimo.
Personas con las que hemos compartido nuestro cuerpo, nuestros besos, nuestra piel, nuestros secretos más íntimos. Personas a las que juramos amor eterno, personas con las que recorrimos el mundo de la mano, personas que hicieron de sus chistes nuestra sutileza, personas con las que nos pasábamos horas y horas hablando hasta que los gritos se hicieron protagonista de una película que empezó siendo de amor, y terminó siendo un thriller de Hitchcock. Personas con las que diseñamos planes y construímos puentes que creíamos indestructibles. Preciosas historias que se esfumaron en un recuerdo amargo. Los mejores años de nuestra vida, nuestro amor hecho hijos y cientos de te quieros que volaron al viento sin dueño. Sin rumbo. Sin prisa.
Y hoy si te veo no me saludas. No te saludo.
Y hoy no te quiero. Hoy te odio.
Y hoy ya no me pareces guapo, ni guapa. ¿Cómo pude fijarme en ti?
Y hoy olvidé todo eso que me enamoró de ti. Aunque bueno, realmente creo que nunca lo estuve.
Y hoy no eres nadie para mi. Ni un amigo, ni una amiga. Y hoy cuando me hablan de ti me sumo a la indiferencia o si aún no lo he superado, te critico hasta quedarme sin más argumento que insultos vacíos de lógica.
Hoy ya no guardo tus fotos. O si. Eso nunca lo sabrás.
Y hoy ni siquiera, me permito el lujo de pensar en ti.
¿No es mohíno? Lo es y mucho.
Para ser un buen ex, debiste ser primero una buena pareja. Y quiero pensar que muchos de nosotros no lo fuimos, porque sino ¿qué sentido tiene odiar a nuestros exs? ¿Qué sentido tiene no darles un espacio en nuestras vidas? ¿Pudimos amar tanto a alguien que hoy ni siquiera nos importa?. Quizás los prejuicios, esta estúpida sociedad que nos ha enseñado a amar de una forma tan tóxica, hace que no esté bien visto tener relación con personas que formaron parte de nuestro pasado. Cuando deberían ser ellos y ellas nuestros mejores amigos. Esas personas con las que compartimos más que con cualquier otra persona en el mundo. Esa persona a la que regalamos nuestra desnudez, el olor a recién levantado y el último beso de cada luna. Esa persona con la que dibujábamos vacaciones, partituras hechas canción sin melodía y personas que creímos nuestra alma gemela. Posiblemente lo fuera. Aunque no durara para siempre.
¿Por qué nos odiamos?
¿Por qué tienes que odiarme?
¿Por qué aunque hoy ya no seamos pareja ni nos una ese vínculo sentimental, no podemos mantener una relación sana, desearnos lo mejor y darnos un abrazo sincero cada vez que nos veamos? Por suerte aún hay ex parejas que lo hacen. Hay ex parejas que supieron afrontar con madurez su ruptura y hoy,  son mejores amigos. Que hoy son padres compañeros de criaturas maravillosas. O son conocidos que se saludan cordialmente y se desean lo mejor. No celan de sus actuales parejas, porque eso, está más que superado.
Supongo que el problema está cuando no se supera. Porque acaso ¿el odio no es una forma de amor? ¿acaso llamar la atención del otro aún siendo de malas formas, no es una manera de decir “ey aún te quiero”?. Si, lo es. Y quizás por eso la gran mayoría de nosotros no es capaz de ver a un ex como lo que fue. Una persona importante en nuestras vidas que por encima de todo, merece el mayor de nuestros respetos. O no. Porque como dije antes “para ser un buen ex, tuviste que ser una buena pareja”. Y entiendo esos casos donde el mal querer hizo mella, donde nunca existió una amistad ni un amor sincero. Entonces en esos casos, se entiende que un ex quede desterrado para siempre.
te ex-quieroMe gusta pensar que aunque tengamos el mismo nombre y apellidos durante toda nuestra vida, que aunque el número de nuestro DNI y Seguridad Social no cambie, realmente podemos llegar a ser varias personas distintas en una misma vida. En mi caso, yo a las quince años no era igual que a los veinte. Ni a los veinticinco era igual a la mujer que soy hoy en día. Estoy hecha de experiencias, de caídas, de estúpidos errores que cometí en el pasado, de melodías rotas y melodías eternas que siempre bailarán al son del sol de octubre. Estoy hecha de ti, de ti y de ti también. Hecha de besos inexpertos y hecha de besos maduros. Estoy hecha de lágrimas, de corazones rotos y de promesas que nunca se escribieron. Estoy hecha de amor, de decepción y de todas esas personas que pasaron por mi vida. Estoy hecha de ex- te quieros, y de todos esos exs que me enseñaron (unos mejor que otros) a ser quién soy hoy en día. ¡GRACIAS!
Porque por muy mal que nos fuera, por muy mal que ese ex o esa ex nos lo hiciese pasar, debemos sentirnos agradecidos.
Agradecidos por lo que nos dieron, por lo que nos quitaron.
Por todo lo que crecimos y aprendimos a su lado.
Por la forma en la que nos amaron, aunque nos amasen mal o simplemente no lo hicieran.
Por esos días de sus vidas que eligieron pasarlo con nosotros y aunque hoy seamos un ex odioso para ellos, en el fondo de nuestro corazón, si alguna vez hubo amor de verdad, hubo amor al fin y al cabo, ese recuerdo perdurará el resto de nuestras vidas.
……….
Hoy que te tengo delante, te miro con los ojos estallados en lágrimas y suplicándole al cielo que no te conviertas TÚ en unos de mis exs. Porque quiero quererte siempre, amarte siempre, contar arrugas a tu lado y decirte al oído en un último suspiro “gracias”.
Te ex-quiero.
Y te ex-querré siempre.
 (Texto integro sacado de: http://elrincondefloricienta.com/2014/10/15/te-ex-quiero/)

martes, 5 de febrero de 2013


La elaboración propia o casera de las runas te ayudará muchísimo a conectar con ellas ya que se suele establece una conexión realmente muy especial.

Elaboración de las Runas

Es parte de la tradición que quien lee las runas tenga un juego elaborado por sí mismo. Sí, puedes fabricar tus propias runas. Si bien se pueden adquirir en el mercado, la elaboración de las runas es un trabajo creativo que le da una energía especial. Elaborar tus runas te conectará mucho más con ellas.

Materiales para la elaboración de las Runas

  • 25 piedras de río o mar (guijarros) de unos 3 cm. de largo.
  • Lápiz o creyón.
  • Hoja cuadriculada.
  • Un pincel medio (Nº 3 a 4)
  • Esmalte azul.
  • Barniz transparente.
  • Palillos (mondadientes)
  • Servilletas de papel.
  • Disolvente para limpiar el pincel.
alfabeto rúnico
La elaboración de tus runas, requiere piedras lisas de color claro. Que tengan tamaño y forma similar, preferiblemente ovaladas. Recoge algunas adicionales para caso de errores, o simplemente para practicar antes de pintar las runas como tal.
También se puede emplear cualquier material natural: madera, suela, arcilla, procurando darles una forma oval.

Procedimiento para la elaboración de las Runas

  • Lavar las 25 piedrecillas cuidadosamente con un jabón natural (de coco, de tierra, de almendras, etc.) y dejarlas secar muy bien, preferiblemente al sol.
  • Sobre hojas de periódico coloca las piedras limpias y secas. Con la ayuda del pincel, cubre cada una con una capa de barniz transparente, primero por un lado y, al estar seco, por el otro. Deja secar muy bien cada lado.
  • Mientras seca el barniz, toma el gráfico con los 24 símbolos rúnicos (recuerda que habrá una runa en blanco o "Runa de Odín", con la cual suman 25) Practica cada runa en la hoja de papel cuadriculado, hasta reproducir lo más fielmente posible los trazos de las runas.
  • El tipo de pintura a utilizar debe tener una pigmentación fuerte, de secado rápido y permanente. Consulta en una tienda de arte.
  • Impregna la punta del palillo, apenas con una gota de pintura y traza suavemente las líneas del carácter rúnico colocando la piedra ovalada en posición vertical, ya que estas piezas deberán tener un sentido derecho e invertido. Con palillos obtendrás trazos definidos. Elimina los excesos de pintura con una servilleta de papel.
  • Reemplaza el palillo con frecuencia para que la punta siempre esté afilada y mantengas la misma precisión.
  • Elaboradas todas las runas, incluso la runa en blanco. Déjalas secar y da una última capa de barniz que dejarás secar según las instrucciones del fabricante.

Bolsa para Runas

Parte de la tradición es la elaboración de la bolsa para guardar las runas. Se recomienda el color azul por ser el color de la capa de Odín. Sin embargo puedes hacerla en otro color, pero debes sentirte seguro al hacerlo.

Materiales para confeccionar la bolsa de las Runas

  • Restos de tela de material natural azul marino o índigo (Lino, algodón o piel)
  • Hilo del mismo color y aguja.
  • 35 cm. de cordón.

Procedimiento para confeccionar la bolsa de las Runas

Bolsa para las runas
Los chamanes rúnicos, utilizaban material natural, como lino o piel. También puedes utilizar algodón.
Lo importante es que el material sea blando y flexible, fácil de manipular.
Tu bolsa puede ser lisa y sencilla o estar decorada con símbolos que sean significativos para ti.
Elabórala a mano o a máquina.
A pesar de exigir un poco más de tus habilidades, no es nada demasiado complicado.
  • Corta dos rectángulos de 17 x 12 cm. aproximadamente.
  • Cóselos por el revés verticalmente y deja abierto el extremo superior.
  • Voltea la bolsa y haz un dobladillo de unos 2 cm. en la abertura.
  • Haz una serie de ojalillos cerca de la boca y pasa un cordón a través de ellos.
  • De este modo podrás cerrar la bolsita para no perder tus runas.





martes, 3 de abril de 2012

Curiosidades de Facebook...

10 cosas que no debes hacer en Facebook si no quieres acabar en la cárcel

1- Subir una foto de tu hijo con una cachimba

Rachel Stieringer, de 19 años de edad, es la madre del pequeño Keystone Heights, y fue acusada de un cargo menor de posesión de parafernalia relacionada con las drogas. Aunque estuvo a un tris de perder la custodia de su hijo, cuando subió a Facebook la imagen del tierno infante en la actitud que delata la imagen.

Alguien avisó a las autoridades de Florida, donde vive, y la madre fue detenida. Luego dijo que el nene se había encontrado la cachimba por casualidad y había comenzado a jugar con ella. Le salvó que el bebé dio negativo en la prueba de THC.

2- Retransmitir un secuestro en directo

Jason Valdez dio todo un ejemplo de cómo usar debidamente las red 2.0. El tipo secuestró a una chica y la retuvo en una habitación de hotel de Utah durante 16 horas. Durante este proceso, se dedicó a actualizar su estado de Facebook continuamente con la evolución del secuestro.

Algunos de sus mensajes decían: “han cortado el teléfono, pero estamos bien, los comentarios de todos significan mucho. Pero el cómo termine está en manos de la poli. Y mi REHÉN, como la llaman, está perfectamente y aguantando conmigo”.

Sus familia intentaba disuadirle, pero no lo consiguió. Acabó en el hospital tras un disparo en el pecho… que él mismo se dio.

Click en leer más para ver las otras 8 historias (Muy entretenidas)


3- Hacer un “sinpa” en el taxi y dejarte el móvil dentro

Un chaval con mucho morro decidió no pagar al taxista que le había llevado a casa. Pero en sus prisas por huir, se dejó el móvil en el coche. Resultado: el taxista aprovechó para actualizar su estado contando todo el incidente: “La pasada noche fui un gilipollas con un taxista y me negué a pagar el viaje, y le amenacé. Cuando me dijo que me llevaría a la comisaría me asusté y planeé salir por patas. Cuando intenté huir, me dejé el móvil en el taxi. Y ahora el taxista me está enseñando una lección escribiendo este post”.


4- “Un momentito, que miro a ver si tengo algo en el Facebook”…

Trevor Jones tiene dos características que se llevan mal: ser ladrón y adicto al Facebook. Así que cuando entró a robar en una casa, no pudo evitar aprovechar el ordenador de los ocupantes para comprobar si tenía mensajes nuevos. El tipo era tan despistado que se olvidó de salir de su cuenta antes de irse: la policía lo tuvo fácil para identificarle posteriormente.

5- Hacerte una foto con un móvil robado conectado a Internet

Este señor robó el bolso de una chica de Atlanta. Dentro se encontraba un móvil de última generación que el tipo deseó probar, así que se sacó una foto ver que calidad ofrecía. Pero su dueño original tenía configurada la función para subir cada foto a su cuenta de Facebook. La policía se mostró “muy emocionada”, dado que rara vez se tiene una foto tan clara en un robo de este tipo.

6- Ofrecer dinero para matar a un ex

Hay quién usa las redes sociales para encontrar trabajo. Es el caso de una mujer que ofreció a través de su muro 1.000 dólares a quien matara a su exnovio y padre su hijo, Corey White, de 22 años. Y en estos tiempos de crisis no hay que dejar pasar cualquier oferta de trabajo, así que a los 15 minutos Timothy Bynum, de 18 años, se ofrecía voluntario.

A finales de agosto, unos días después, White aparecía muerto en medio de la calle con un disparo en el pecho. La ex-novia y el rufián fueron puestos entre rejas con altísimas fianzas, acusados de asesinato y conspiración, si bien la investigación aún continúa en otros frentes.

7- Regalar cosas robadas a una novia presumida

Amor, crimen y Facebook, una receta bastante peligrosa. Robert Driscoll, de 21 años, robó un anillo valorado en más de 8.000 euros en una joyería de Pittsburgh. Al poco su novia, Crystal Yamnitzky, de 20 años, compartía con sus amigos una foto del anillo: “me encanta el regalo que me ha hecho mi Rob”. La policía fue informada del asunto: poco después unas cámaras recogían como Driscoll vendía la joya en una tienda de empeños.

8- ¡Cuidadín a quién aceptas como amigo (o de quién dejas de serlo)!

Hay gente que se toma las cosas demasiado en serio. Jennifer Christine Harris es una mujer ya de 30 años que perdió el control cuando una amiga suya le “quitó de amigos” del FB. Ella y Nikki Rasmussen se conocen desde hace años, pero cuando la primera organizó una fiesta a la que nadie quiso confirmar su asistencia por FB, ni siquiera su amiga, comenzaron las discusiones. Nikki terminó la amistad, la cosa siguió por móvil… y en un arrebato de furia, Jennifer se acercó por la casa de su “amiga” y le prendió fuego.

9- Robar un banco con la misma ropa que muestras en las fotos de tu perfil

Investigadores del FBI detuvieron a un hombre acusado de robar cinco bancos en el área de Detroit tras comprobar las fotos de las cámaras de seguridad y cruzarlas con varios perfiles de Facebook. El agente Juan Herrera recibió un soplo de un informador diciendo que el ladrón se apellidaba Wilson. En realidad se llamaba Anthony Wilson; y lo cogieron porque al ir a su perfil se lo encontraron en varias fotos vestido igual que como le mostraban las cámaras de los bancos.

10- Engancharte al Mafia Wars siendo abogada

Bettysue Higgins, de Maine, tenía un trabajo en una firma de abogados. Allí comenzó a desfalcar dinero, falsificando cheques durante unos 16 meses: llegó a coger sin autorización más de 166.000 dólares. El destinatario de esos cheque eran… las firmas detrás de los jueguecitos Mafia Wars y Yo Ville, que ofrecen objetos y ventajas especiales a los usuarios que deseen pagar con ello.

La mujer de 54 años ya tenía antecedentes, así que el pasado día 3 fue condenado definitivamente a un año de prisión. Su casa fue embargada para pagar la deuda.

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

/* 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 0
output("[%s] doing a reality check on level [%d] dreamers\n",
dattr->name, dattr->level);
#endif
pthread_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 0
output("Dreamer [%s] is in LIMBO. So ignoring\n", dreamer->name);
#endif
continue;
}
if(!(dreamer->shared_state & DREAMER_KICK_BACK))
{
#if 0
output("Dreamer [%s] is not yet in reality\n", dreamer->name);
#endif
pthread_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, &param) == 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;
}

♠Diseños♠