Exemplo n.º 1
0
static scpi_bool_t SCPI_ErrorAddInternal(scpi_t * context, int16_t err, char * info, size_t info_len) {
    scpi_error_t error_value;
    char * info_ptr = info ? SCPIDEFINE_strndup(&context->error_info_heap, info, info_len) : NULL;
    SCPI_ERROR_SETVAL(&error_value, err, info_ptr);
    if (!fifo_add(&context->error_queue, &error_value)) {
        SCPIDEFINE_free(&context->error_info_heap, error_value.device_dependent_info, true);
        fifo_remove_last(&context->error_queue, &error_value);
        SCPIDEFINE_free(&context->error_info_heap, error_value.device_dependent_info, true);
        SCPI_ERROR_SETVAL(&error_value, SCPI_ERROR_QUEUE_OVERFLOW, NULL);
        fifo_add(&context->error_queue, &error_value);
        return FALSE;
    }
    return TRUE;
}
Exemplo n.º 2
0
void SCPIParser::SCPI_ErrorAddInternal( int16_t err) {
    /*
     * // FreeRTOS
     * xQueueSend((xQueueHandle)context.error_queue, &err, 0);
     */

    /* basic FIFO */
    fifo_add((fifo_t *)context.error_queue, err);
}
Exemplo n.º 3
0
static void SCPI_ErrorAddInternal(scpi_t * context, int16_t err) {
    /*
     * // FreeRTOS
     * xQueueSend((xQueueHandle)context->error_queue, &err, 0);
     */

    /* basic FIFO */
    fifo_add((fifo_t *)context->error_queue, err);
}
Exemplo n.º 4
0
static void testFifo() {
    scpi_fifo_t fifo;
    fifo_init(&fifo);
    int16_t value;

    fifo.size = 4;

#define TEST_FIFO_COUNT(n)                      \
    do {                                        \
        fifo_count(&fifo, &value);              \
        CU_ASSERT_EQUAL(value, n);              \
    } while(0)                                  \
    

    TEST_FIFO_COUNT(0);
    CU_ASSERT_TRUE(fifo_add(&fifo, 1));
    TEST_FIFO_COUNT(1);
    CU_ASSERT_TRUE(fifo_add(&fifo, 2));
    TEST_FIFO_COUNT(2);
    CU_ASSERT_TRUE(fifo_add(&fifo, 3));
    TEST_FIFO_COUNT(3);
    CU_ASSERT_TRUE(fifo_add(&fifo, 4));
    TEST_FIFO_COUNT(4);
    CU_ASSERT_TRUE(fifo_add(&fifo, 1));
    TEST_FIFO_COUNT(4);

    CU_ASSERT_EQUAL(fifo.data[0], 1);
    CU_ASSERT_EQUAL(fifo.data[1], 2);
    CU_ASSERT_EQUAL(fifo.data[2], 3);
    CU_ASSERT_EQUAL(fifo.data[3], 4);

    CU_ASSERT_TRUE(fifo_remove(&fifo, &value));
    CU_ASSERT_EQUAL(value, 2);
    TEST_FIFO_COUNT(3);

    CU_ASSERT_TRUE(fifo_add(&fifo, 5));
    TEST_FIFO_COUNT(4);

    CU_ASSERT_TRUE(fifo_remove(&fifo, &value));
    CU_ASSERT_EQUAL(value, 3);
    TEST_FIFO_COUNT(3);

    CU_ASSERT_TRUE(fifo_remove(&fifo, &value));
    CU_ASSERT_EQUAL(value, 4);
    TEST_FIFO_COUNT(2);

    CU_ASSERT_TRUE(fifo_remove(&fifo, &value));
    CU_ASSERT_EQUAL(value, 1);
    TEST_FIFO_COUNT(1);

    CU_ASSERT_TRUE(fifo_remove(&fifo, &value));
    CU_ASSERT_EQUAL(value, 5);
    TEST_FIFO_COUNT(0);
    
    CU_ASSERT_FALSE(fifo_remove(&fifo, &value));
    TEST_FIFO_COUNT(0);
}
Exemplo n.º 5
0
static void
finalize_phase_one(workqueue_t *wq)
{
	int startslot, i;

	/*
	 * wip slots are cleared out only when maxbatchsz td's have been merged
	 * into them.  We're not guaranteed that the number of files we're
	 * merging is a multiple of maxbatchsz, so there will be some partial
	 * groups in the wip array.  Move them to the done queue in batch ID
	 * order, starting with the slot containing the next batch that would
	 * have been placed on the done queue, followed by the others.
	 * One thread will be doing this while the others wait at the barrier
	 * back in worker_thread(), so we don't need to worry about pesky things
	 * like locks.
	 */

	for (startslot = -1, i = 0; i < wq->wq_nwipslots; i++) {
		if (wq->wq_wip[i].wip_batchid == wq->wq_lastdonebatch + 1) {
			startslot = i;
			break;
		}
	}

	assert(startslot != -1);

	for (i = startslot; i < startslot + wq->wq_nwipslots; i++) {
		int slotnum = i % wq->wq_nwipslots;
		wip_t *wipslot = &wq->wq_wip[slotnum];

		if (wipslot->wip_td != NULL) {
			debug(2, "clearing slot %d (%d) (saving %d)\n",
			    slotnum, i, wipslot->wip_nmerged);
		} else
			debug(2, "clearing slot %d (%d)\n", slotnum, i);

		if (wipslot->wip_td != NULL) {
			fifo_add(wq->wq_donequeue, wipslot->wip_td);
			wq->wq_wip[slotnum].wip_td = NULL;
		}
	}

	wq->wq_lastdonebatch = wq->wq_next_batchid++;

	debug(2, "phase one done: donequeue has %d items\n",
	    fifo_len(wq->wq_donequeue));
}
Exemplo n.º 6
0
int main (void)
{
	long long put = 0, get = 0;
	char str[32];
	fifo_t fifo = fifo_create();
	
	while (1)
	{
		int i;
		int block = random() % BLOCK;
		
		for (i = 0; i < block; i++)
		{
			if ((put & DISPLAY) == DISPLAY)
			{
				printf("%lli... (size %lli)\r", put, put - get);
				fflush(stdout);
			}

			sprintf(str, "%lli", put++);
			fifo_add(fifo, str);
		}

		block = random() % BLOCK;
		for (i = 0; i < block; i++)
		{
			char* out = fifo_getdel(fifo);
			if (!out)
				break;
			long long test = atoll(out);
			
			if (test != get)
			{
				fprintf(stderr, "error, getting %lli (%s), should be %lli\n", test, out, get);
				exit(1);
			}
			get++;
			
			free(out);
		}
	}
	
	return 0;
}
Exemplo n.º 7
0
static void
wip_save_work(workqueue_t *wq, wip_t *slot, int slotnum)
{
	pthread_mutex_lock(&wq->wq_donequeue_lock);

	while (wq->wq_lastdonebatch + 1 < slot->wip_batchid)
		pthread_cond_wait(&slot->wip_cv, &wq->wq_donequeue_lock);
	assert(wq->wq_lastdonebatch + 1 == slot->wip_batchid);

	fifo_add(wq->wq_donequeue, slot->wip_td);
	wq->wq_lastdonebatch++;
	pthread_cond_signal(&wq->wq_wip[(slotnum + 1) %
	    wq->wq_nwipslots].wip_cv);

	/* reset the slot for next use */
	slot->wip_td = NULL;
	slot->wip_batchid = wq->wq_next_batchid++;

	pthread_mutex_unlock(&wq->wq_donequeue_lock);
}
Exemplo n.º 8
0
status_t fifo_write_signal(fifo p, void *data)
{
    status_t rc;

    assert(p != NULL);
    assert(data != NULL);

    if (!fifo_lock(p))
        return failure;

    if (!fifo_add(p, data)) {
        fifo_unlock(p);
        return failure;
    }

    rc = fifo_signal(p);
    fifo_unlock(p);

    return rc;
}
Exemplo n.º 9
0
/*
 * Pass a tdata_t tree, built from an input file, off to the work queue for
 * consumption by worker threads.
 */
static int
merge_ctf_cb(tdata_t *td, char *name, void *arg)
{
	workqueue_t *wq = arg;

	debug(3, "Adding tdata %p for processing\n", (void *)td);

	pthread_mutex_lock(&wq->wq_queue_lock);
	while (fifo_len(wq->wq_queue) > wq->wq_ithrottle) {
		debug(2, "Throttling input (len = %d, throttle = %d)\n",
		    fifo_len(wq->wq_queue), wq->wq_ithrottle);
		pthread_cond_wait(&wq->wq_work_removed, &wq->wq_queue_lock);
	}

	fifo_add(wq->wq_queue, td);
	debug(1, "Thread %d announcing %s\n", pthread_self(), name);
	pthread_cond_broadcast(&wq->wq_work_avail);
	pthread_mutex_unlock(&wq->wq_queue_lock);

	return (1);
}
static void usb_ctrl_msg(struct st5481_adapter *adapter,
			 u8 request, u8 requesttype, u16 value, u16 index,
			 ctrl_complete_t complete, void *context)
{
	struct st5481_ctrl *ctrl = &adapter->ctrl;
	int w_index;
	struct ctrl_msg *ctrl_msg;

	if ((w_index = fifo_add(&ctrl->msg_fifo.f)) < 0) {
		WARNING("control msg FIFO full");
		return;
	}
	ctrl_msg = &ctrl->msg_fifo.data[w_index];

	ctrl_msg->dr.bRequestType = requesttype;
	ctrl_msg->dr.bRequest = request;
	ctrl_msg->dr.wValue = cpu_to_le16p(&value);
	ctrl_msg->dr.wIndex = cpu_to_le16p(&index);
	ctrl_msg->dr.wLength = 0;
	ctrl_msg->complete = complete;
	ctrl_msg->context = context;

	usb_next_ctrl_msg(ctrl->urb, adapter);
}
Exemplo n.º 11
0
static void
worker_runphase2(workqueue_t *wq)
{
	tdata_t *pow1, *pow2;
	int batchid;

	for (;;) {
		pthread_mutex_lock(&wq->wq_queue_lock);

		if (wq->wq_ninqueue == 1) {
			pthread_cond_broadcast(&wq->wq_work_avail);
			pthread_mutex_unlock(&wq->wq_queue_lock);

			debug(2, "%d: entering p2 completion barrier\n",
			    pthread_self());
			if (barrier_wait(&wq->wq_bar1)) {
				pthread_mutex_lock(&wq->wq_queue_lock);
				wq->wq_alldone = 1;
				pthread_cond_signal(&wq->wq_alldone_cv);
				pthread_mutex_unlock(&wq->wq_queue_lock);
			}

			return;
		}

		if (fifo_len(wq->wq_queue) < 2) {
			pthread_cond_wait(&wq->wq_work_avail,
			    &wq->wq_queue_lock);
			pthread_mutex_unlock(&wq->wq_queue_lock);
			continue;
		}

		/* there's work to be done! */
		pow1 = fifo_remove(wq->wq_queue);
		pow2 = fifo_remove(wq->wq_queue);
		wq->wq_ninqueue -= 2;

		batchid = wq->wq_next_batchid++;

		pthread_mutex_unlock(&wq->wq_queue_lock);

		debug(2, "%d: merging %p into %p\n", pthread_self(),
		    (void *)pow1, (void *)pow2);
		merge_into_master(pow1, pow2, NULL, 0);
		tdata_free(pow1);

		/*
		 * merging is complete.  place at the tail of the queue in
		 * proper order.
		 */
		pthread_mutex_lock(&wq->wq_queue_lock);
		while (wq->wq_lastdonebatch + 1 != batchid) {
			pthread_cond_wait(&wq->wq_done_cv,
			    &wq->wq_queue_lock);
		}

		wq->wq_lastdonebatch = batchid;

		fifo_add(wq->wq_queue, pow2);
		debug(2, "%d: added %p to queue, len now %d, ninqueue %d\n",
		    pthread_self(), (void *)pow2, fifo_len(wq->wq_queue),
		    wq->wq_ninqueue);
		pthread_cond_broadcast(&wq->wq_done_cv);
		pthread_cond_signal(&wq->wq_work_avail);
		pthread_mutex_unlock(&wq->wq_queue_lock);
	}
}
Exemplo n.º 12
0
static void SCPI_ErrorAddInternal(scpi_t * context, int16_t err) {
    if (!fifo_add(&context->error_queue, err)) {
        fifo_remove_last(&context->error_queue, NULL);
        fifo_add(&context->error_queue, SCPI_ERROR_QUEUE_OVERFLOW);
    }
}
Exemplo n.º 13
0
int main(void)
{
    fifo f;
    size_t i, nelem;
    status_t rc;
    char dummydata[1000] = "Hello";
    clock_t stop, start;
    double duration;


    nelem = 1*1000*1000;
    f = fifo_new(nelem);

#if 1

    /* Fill the fifo completely */
    start = clock();
    for (i = 0; i < nelem; i++) {
        rc = fifo_add(f, dummydata);
        assert(rc != 0);
    }
    stop = clock();
    duration = (stop - start) * 1.0 / CLOCKS_PER_SEC;
    printf("%s: Added %lu elements in %f seconds\n", __FILE__, (unsigned long)nelem, duration);

    assert(fifo_nelem(f) == nelem);

    /* Test fifo_peek() */
    for (i = 0; i < nelem; i++) {
        const char *s = fifo_peek(f, i);
        /* Stupid workaround for gcc 4.0.2 optimization in conjunction with assert() */
        int xi;
        xi = (s != NULL); assert(xi);
        xi = (strcmp(s, dummydata) == 0); assert(xi);
    }

    /* Add a new one, this should fail */
    assert(fifo_add(f, dummydata) == 0);

    /* Now read two and then add one. That should be possible */
    assert(fifo_get(f));
    assert(fifo_get(f));
    assert(fifo_nelem(f) == nelem - 2);
    assert(fifo_add(f, dummydata) != 0);
    assert(fifo_nelem(f) == nelem - 1);

    /* Test fifo_peek() */
    for (i = 0; i < fifo_nelem(f); i++) {
        const char *s = fifo_peek(f, i);
        int xi;
        xi = (s != NULL); assert(xi);
        xi = (strcmp(s, dummydata) == 0); assert(xi);
    }

    /* The first should be OK, the next must fail */
    assert(fifo_add(f, dummydata) != 0);
    assert(fifo_nelem(f) == nelem);

    assert(fifo_add(f, dummydata) == 0);
    assert(fifo_nelem(f) == nelem);

    start = clock();
    for (i = 0; i < nelem; i++) {
        char *x = fifo_get(f);
        (void)x;
    }
    stop = clock();
    duration = (stop - start) * 1.0 / CLOCKS_PER_SEC;
    printf("%s: Got %lu elements in %f seconds\n", __FILE__, (unsigned long)nelem, duration);

#endif

    /* Now check signalling and wait for data.
     * We start two threads, a reader and a writer.
     * The writer writes n times to the fifo and the reader
     * prints the data.
     * This thread joins the writer and calls fifo_wake() when
     * the writer is done, to stop the reader thread in a controlled
     * manner.
     */
     {
         pthread_t w, r;

        pthread_create(&r, NULL, reader, f);
        pthread_create(&w, NULL, writer, f);
        pthread_join(w, NULL);
        if (!fifo_wake(f))
            exit(EXIT_FAILURE);

        pthread_join(r, NULL);
     }

    fifo_free(f, free);
    return 0;
}
Exemplo n.º 14
0
void cis_run (void)
{
  int temp_int = 0, temp_int2 = 0;
  int i = 0, r, w;
  int eventcount = 0;
  connection *read_events[__MAXFDS__];
  connection *write_events[__MAXFDS__];

  fifo_root *global_recvq = NULL;
  linklist_iter *reaper_iter = NULL;

  connection *temp = NULL;
  char *line;

  int patience = 250;

  reactor_running = true;

  global_recvq = fifo_create();

  /* main loop */
  for(;reactor_running;)
  {

    /** Grab some socket events to play with */
    eventcount = socketengine->wait(read_events, write_events, patience);
    r = w = 0;

    /** Run through the existing connections looking for data to read */
    for(i = 0; (r+w) < eventcount; i++)
    {
      if (read_events[i] != NULL)
      {
        r++;
        temp_int = read_events[i]->recvq->queue_size;
        conn_read_to_recvq(read_events[i]);
        if ((read_events[i]->recvq->queue_size > temp_int) && ((equal_fairness == 0) || (temp_int == 0)))
          fifo_add(global_recvq, read_events[i]);
        /* Don't wait for data! too much to do! */
        patience = 0;
      }
      if (write_events[i] != NULL)
      {
        w++;
        if (write_events[i]->state.connecting == 1)
        {
            assert(getsockopt(write_events[i]->fd, SOL_SOCKET, SO_ERROR, &temp_int, &temp_int2) == 0);
            if (temp_int == 0)
            {
                write_events[i]->connected(write_events[i]);
                write_events[i]->state.connecting = 0;
            }
            else
            {
                write_events[i]->connect_failed(write_events[i], temp_int);
                write_events[i]->state.remote_closed = 1;
                write_events[i]->state.local_read_shutdown = 1;
                write_events[i]->state.local_write_shutdown = 1;
                socketengine->del(write_events[i]);
                cis_reap_connection(write_events[i]);
            }
        }
        else
            conn_send_from_sendq(write_events[i]);
      }
    } // foreach (event)

    /** Process some of the readq */

    if (global_recvq->members > 0)
    {
      for (i = 0; i <= 20; i++)
      {
        temp = fifo_pop(global_recvq);
        if (temp == NULL)
        {
          /* We seem to be out of connections to process... Have more patience waiting for new data ...*/
          patience = 250;
          break;
        }
        if ((temp->state.local_read_shutdown == 0)&&(temp->recvq->queue_size > 0))
        {
          /* Local dead connections don't get processed ... remote dead ones -do- (since they died after sending this...) */
          if (temp->callback_read)
            temp->callback_read(temp);
          else
            buffer_empty(temp->recvq);

          /* If it doesn't have any more messages left, nuke it from the queue... */
          if (temp->recvq->queue_size == 0)
            fifo_del(global_recvq, temp);
          else
          {
            if (equal_fairness == 1)
            {
              fifo_del(global_recvq, temp);
              fifo_add(global_recvq, temp);
            }
            else
            {
              /* We shove it back on the end of the queue,
               * just in case there are insufficent instances to cover the buffer content.
               *
               * While this behaviour won't break the code it isn't true first come first served,
               * and it will have a performance impact.
               *
               * TODO: It would be nice to have an alternative ...
               * possibly making conn_read_to_recvq return a line count to allow multiple additions
               */
              fifo_add(global_recvq, temp);
            }
          }

          if (global_recvq->members == 0)
          {
            patience = 250; /* Nothing to do, so I don't mind wait a while */
          }
          break;
        }
        else
        {
          /* So this is either locally dead, or has no recvq ... both could happen, but ignore it either way */
          if (temp->recvq->queue_size > 0)
          {
            /* Must be locally dead but with a recvq still ... this shouldn't be possible? */
            buffer_empty(temp->recvq);
          }

          /* In any case, if we're ignoring it, might as well remove it completely ... */
          fifo_del(global_recvq, temp);

          /* Since we didn't do much with this one, we'll try another pass... */
          i--;
        }
      }
    }

    /** Attempt to reap connections... */
    reaper_iter = linklist_iter_create(reaper_list);
    while (temp = linklist_iter_next(reaper_iter))
    {
      /* Has this connection reached the end of it's life? */
      if (((temp->state.remote_closed == 1) && (temp->recvq->queue_size == 0)) ||
           (temp->state.local_read_shutdown == 1) && (temp->sendq->queue_size == 0))
      {
        /* Remove it from any relevant queues... */
        linklist_iter_del(reaper_iter);
        fifo_del(global_recvq,temp);
        /* Make sure it's all closed down... */
        temp->state.local_write_shutdown = 1;
        temp->close(temp);
        /* Free the important stuff.... */
        if (temp->recvq)			buffer_free(temp->recvq);
        if (temp->sendq)			buffer_free(temp->sendq);
        sfree(temp);
      }
    }
    linklist_iter_free(reaper_iter);

    timers_process();
  }
  return;
}
Exemplo n.º 15
0
int main(int argc, char **argv)
{
	int **A = NULL;
	int **N = NULL;
	int **PLC = NULL;
	int *GL = NULL;
	FILE *fichier = NULL;
	int nbPlaces=0, nbLevels=0;
	int *listePositif = NULL;
	int *listeNegatif = NULL;
	int *listeAVisiter = NULL;
	int i, j, k, buf;

	/* 
	 * Récupération de la Matrice
	 */

	/* Ouverture du fichier */
	fichier = fopen("input.data", "r");
	if(fichier == NULL)
		fprintf(stderr,"Erreur : Ouverture du fichier impossible :'(\n");

	/* Récupération du nombre de zones */
	fscanf(fichier, "%d", &nbPlaces);

	/* Allocation de la mémoire pour contenir la matrice */
	A = (int**) malloc(sizeof(int*)*nbPlaces);
	for(i=0; i<nbPlaces; i++)
		A[i] = (int*) malloc(sizeof(int)*nbPlaces);

	/* Récupération des données et stoquage dans la matrice */
	for(i=0; i<nbPlaces; i++)
		for(j=0; j<nbPlaces; j++)
			fscanf(fichier, "%d", &A[i][j]);

	/* Fermeture du fichier */
	fclose(fichier);


	/*
	 * Recherche des composants fortement connectés
	 */

	/* Allocation de la mémoire pour enregistrer les niveaux et pour contenir des tableaux temporaires */
	GL = (int*) malloc(sizeof(int)*nbPlaces);
	listePositif = (int*) malloc(sizeof(int)*nbPlaces);
	listeNegatif = (int*) malloc(sizeof(int)*nbPlaces);
	listeAVisiter = (int*) malloc(sizeof(int)*nbPlaces);
	for(i=0; i<nbPlaces; i++)
	{
		listePositif[i] = -1;
		listeNegatif[i] = -1;
		listeAVisiter[i] = -1;
		GL[i] = -1;
	}

	/* On va effectuer la recherche depuis chaque point du graph (sauf si elle est déjà dans un level) */
	for(i=0; i<nbPlaces; i++)
	{
		printf("=====================================\n Research starting from the place %2d \n=====================================\n", i);
		if(GL[i] == -1)
		{
			/* Remplissage de la liste positive */
			fifo_add(listeAVisiter, nbPlaces, i);
			while(fifo_isEmpty(listeAVisiter, nbPlaces) == 0)
			{
				buf = fifo_pop(listeAVisiter, nbPlaces);
				fifo_add(listePositif, nbPlaces, buf);
				for(j=0;j<nbPlaces;j++)
					if(A[buf][j] == 1)
					{
						if(fifo_search(listePositif, nbPlaces, j) == -1)
						{
							fifo_add(listeAVisiter, nbPlaces, j);
						}
					}
			}
			printf("--> Places in the '+' list :\n    ");
			for(j=0;j<fifo_count(listePositif, nbPlaces);j++)
				printf("%2d ", listePositif[j]);
			printf("\n");

			/* Remplissage de la liste negative */
			fifo_add(listeAVisiter, nbPlaces, i);
			while(fifo_isEmpty(listeAVisiter, nbPlaces) == 0)
			{
				buf = fifo_pop(listeAVisiter, nbPlaces);
				fifo_add(listeNegatif, nbPlaces, buf);
				for(j=0;j<nbPlaces;j++)
					if(A[j][buf] == 1 && fifo_search(listeNegatif, nbPlaces, j) == -1)
						fifo_add(listeAVisiter, nbPlaces, j);

			}
			printf("--> Places in the '-' list :\n    ");
                        for(j=0;j<fifo_count(listeNegatif, nbPlaces);j++)
				printf("%2d ", listeNegatif[j]);
			printf("\n");

			/* Recherche d'elements presents dans les deux listes */
			printf("--> Intersection :\n    ");
			for(j=0;j<nbPlaces;j++)
			{
				for(k=0;k<nbPlaces;k++)
					if(listePositif[j] == listeNegatif[k] && listePositif[j] != -1)
					{
						GL[listePositif[j]] = nbLevels;
						printf("%2d ", listePositif[j]);
					}
			}
			printf("\n--> Saving them in the new level n°%2d\n\n", nbLevels);
			nbLevels++;

			/* Vidage des deux listes */
			for(j=0;j<nbPlaces;j++)
			{
				listePositif[j] = -1;
				listeNegatif[j] = -1;
			}
		}
		else
			printf("--> Already in the level n°%2d\n\n", GL[i]);
	}

	printf("\n\n\n========\n Levels\n========\n");
	for(i=0;i<nbPlaces;i++)
		printf("--> Place %2d is in the Level n°%2d\n", i, GL[i]);

	printf("\n");
	for(i=0;i<nbLevels;i++)
	{
		k = 0;
		printf("{");
		for(j=0; j<nbPlaces; j++)
			if(GL[j] == i)
			{
				if(k == 1)
					printf(";");
				else
					k = 1;
				printf("%2d", j);
			}
		printf(" } ");
	}
	printf("\n");


	/*
	 * Création de la matrice réduite
	 */

	/* Allocation et initialisation de la matrice réduite */
	N = (int**) malloc(sizeof(int*)*nbLevels);
	for(i=0; i<nbLevels; i++)
	{
		N[i] = (int*) malloc(sizeof(int)*nbLevels);
		for(j=0; j<nbLevels; j++)
			N[i][j] = 0;
	}

	/* Remplissage de la-dite matrice */
	for(i=0; i<nbPlaces; i++)
	{
		for(j=0; j<nbPlaces; j++)
		{
			if(A[i][j] == 1)
			{
				N[GL[i]][GL[j]]++;
			}
		}
	}

	printf("\n================\n Reduced Matrix\n================\n");
	for(i=0; i<nbLevels; i++)
	{
		for(j=0; j<nbLevels; j++)
			printf("%2d ", N[i][j]);
		printf("\n");
	}


	/*
	 * Calcul du plus long chemin entre le premier et le dernier niveau
	 */

	/* Allocation et Reallocation d'une partie de mémoire précédement utilisé et mise à zéro */
	listeAVisiter = (int*) realloc(listeAVisiter, sizeof(int)*nbLevels);
	PLC = (int**) malloc(sizeof(int*)*nbLevels);
	for(i=0; i<nbLevels; i++)
	{
		listeAVisiter[i] = -1;
		PLC[i] = (int*) malloc(sizeof(int)*nbLevels);
		for(j=0; j<nbLevels; j++)
			PLC[i][j] = -1;
	}	

	/* Application de l'algo de calcul du plus long chemin */
	fifo_add(listeAVisiter, nbLevels, GL[0]);
	while(fifo_isEmpty(listeAVisiter, nbLevels) == 0)
	{
		buf = fifo_pop(listeAVisiter, nbLevels);
		for(i=0; i<nbLevels; i++)
			if(N[buf][i] >= 1 && buf != i)
			{
				if(fifo_count(PLC[buf], nbLevels)+1 > fifo_count(PLC[i], nbLevels))
				{
					for(j=0; j<nbLevels; j++)
						PLC[i][j] = PLC[buf][j];
					fifo_add(PLC[i], nbLevels, buf);
					fifo_add(listeAVisiter, nbLevels, i);
				}
			}

	}

	printf("\n==============\n Longest path\n==============\n");
	if(fifo_isEmpty(PLC[GL[nbPlaces-1]], nbLevels) == 0)
		k = GL[nbPlaces-1];
	else
	{
		k = 0;
		for(i=1; i<nbLevels; i++)
			if(fifo_count(PLC[i], nbLevels) > fifo_count(PLC[k], nbLevels))
				k = i;
	}
	printf("--> { ");
	for(i=0; i<nbLevels && PLC[k][i] != -1; i++)
	{
		printf("%d ; ", PLC[k][i]);
	}
	printf("%d }\n", k);


	/*
	 * Generation d'une image du graph (idée par Jérome BOURSIER, merci à lui !)
	 */

	/* Création du fichier */
	fichier = fopen("graph.dot","w");
	fprintf(fichier, "digraph graphAG44\n{\n");

	/* Enregistrement des Niveaux */
	srand(time(NULL));
	for(i=0; i<nbLevels; i++)
	{
		fprintf(fichier, "\tsubgraph sub%d\n\t{\n\t\tnode [style=filled,color=\"#%2x%2x%2x\"];\n", i,rand()%225, rand()%225, rand()%225);
		for(j=0; j<nbPlaces; j++)
			if(GL[j] == i)
				fprintf(fichier, "\t\t%d;\n", j);
		fprintf(fichier, "\t}\n\n");
	}

	/* Enregistrement des Places */
	for(i=0; i<nbPlaces; i++)
		for(j=0; j<nbPlaces; j++)
			if(A[i][j] == 1)
				fprintf(fichier, "\t%d -> %d;\n", i, j);
	fprintf(fichier, "}");
	fclose(fichier);

	/* Appel au programme dot pour generer l'image a partir du fichier */
	if(fork() == 0)
		execlp("dot", "dot", "-Tpng", "graph.dot", "-o", "graph.png", NULL);
        if(fork() == 0)
                execlp("eog", "eog", "graph.png", NULL);


	/*
	 * Libération de la mémoire allouée
	 */

	for(i=0; i<nbPlaces; i++)
		free(A[i]);
	free(A);
	for(i=0; i<nbLevels; i++)
	{
		free(N[i]);
		free(PLC[i]);
	}
	free(N);
	free(PLC);
	free(GL);
	free(listePositif);
	free(listeNegatif);
	free(listeAVisiter);

	return 0;
}