Fusion:Shared Memory Example

From DirectFBWiki

fusionee_master.c

This program will create a simple process that will initialize an arena, allocate some shared memory and publish a pointer to it via the arena. The steps are quite straightforward :

  • Initialize the fusion world
  • Initialize the shared memory pool
  • Initialize a new arena
  • Allocate space for our data in the shared memory pool
  • Fill this memory space with something
  • Publish a pointer to it in our brand new arena

When shutdown the arena we'll have to :

  • Get a pointer to the shared memory
  • Free that memory
  • Exit the arena
  • Free the shared memory pool
  • Exit the fusion world
#include <stdio.h>                       
#include <unistd.h>
#include <stdbool.h>
#include <linux/fusion.h>
#include <fusion/fusion.h>
#include <fusion/shmalloc.h>
#include <fusion/call.h>
#include <fusion/arena.h>
                        
// ABI version for sanity check
#define DFB_ABI  70 
 
enum {
   NEW_WORLD = -1,
   EXISTING_WORLD
} FusionWorldType;

// Shared memory pool size
#define SHM_POOL_SIZE 0x1000000

FusionWorld         *world;
FusionSHMPoolShared *pool;

/*
 * Callback function called from fusion_arena_enter()
 * Add here all variables that live in shared memory
 */
int initialize(FusionArena *arena, void *ctx) {
   char *str = NULL;

   printf("\t\t\tAllocate SHM for field in Arena (%s)\n", __FUNCTION__);
   str = (char *)SHMALLOC(pool, 1024);

   sprintf(str, "String in Arena!!!");
   fusion_arena_add_shared_field(arena, "string1", (void *)str);
   printf("\t\t\tThe string is shared? ");
   fusion_is_shared(world, str) ? printf("Yes") : printf("No");
   printf(" (%s)\n", __FUNCTION__);

   return 0;
}

/*
 * Callback function called from fusion_arena_enter()
 */
int shutdown(FusionArena *arena, void *ctx, bool emergency) {
   char *str = NULL;

   fusion_arena_get_shared_field(arena, "string1", (void *)&str);

   printf("\n\t\t\tFree shared memory (%s)\n\n", __FUNCTION__);
   SHFREE(pool, str);

   return 0;
}

int main () {
   int         ret;
   char        c;
   void        *ctx;
   FusionArena *arena;

   printf("Creating Fusion world (%s)\n", __FUNCTION__);
   fusion_enter(NEW_WORLD, DFB_ABI, FER_MASTER, &world);
   printf("Fusion world created with index %d (%s)\n",
       fusion_world_index(world), __FUNCTION__);
   printf("Is this the master? ");
   fusion_master(world) ? printf("Yes") : printf("No");
   printf(" (%s)\n", __FUNCTION__);

   printf("\tCreating SHM pool (%s)\n", __FUNCTION__);
   fusion_shm_pool_create(world, "WM SHM pool", SHM_POOL_SIZE, 0, &pool);

   printf("\t\tCreating Arena (%s)\n", __FUNCTION__);
   fusion_arena_enter(world, "WM Arena", initialize, NULL, &ctx, &arena, &ret);


   printf("\n\t\tPress enter to exit (%s)\n", __FUNCTION__);
   read(1, &c, 1);


   printf("\t\tShutting down Arena (%s)\n", __FUNCTION__);
   fusion_arena_exit(arena, shutdown, NULL, &ctx, 0, &ret);

   printf("\tDestroying SHM pool (%s)\n", __FUNCTION__);
   fusion_shm_pool_destroy(world, pool);

   printf("Exiting Fusion world (%s)\n", __FUNCTION__);
   fusion_exit(world, 0);

   return 0;
}

fusionee_slave.c

Now we've got some shared memory that we can reach by entering the Arena. So let's write a little program that uses this arena to get the content of the shared memory. So we'll have to:

  • Enter the existing fusion world
  • Enter the arena using the join callback
  • Get a pointer to the shared memory
  • Leave the arena using the leave callback
  • Leave the fusion world
#include <stdio.h>
#include <unistd.h>
#include <linux/fusion.h>
#include <fusion/fusion.h>
#include <fusion/shmalloc.h>
#include <fusion/arena.h>

// ABI version for sanity check
#define DFB_ABI  70

enum {
   NEW_WORLD = -1,
   EXISTING_WORLD
} FusionWorldType;

FusionWorld         *world;

/*
 * Callback function called from fusion_arena_enter()
 */
int join(FusionArena *arena, void *ctx) {
   char *str = NULL;

   printf("\t\tJoin Arena (%s)\n", __FUNCTION__);

   fusion_arena_get_shared_field(arena, "string1", (void *)&str);
   printf("\t\tString in SHM: %s\n", str);

   return 0;
}

/*
 * Callback function called from fusion_arena_exit()
 */
int leave(FusionArena *arena, void *ctx, bool emergency) {
   printf("\t\tLeave Arena (%s)\n", __FUNCTION__);

   return 0;
}

int main() {
   int        ret;
   char        c;
   void        *ctx;
   FusionArena *arena;

   printf("Join Fusion world (%s)\n", __FUNCTION__);
   fusion_enter(EXISTING_WORLD, DFB_ABI, FER_SLAVE, &world);
   printf("Fusion world joined with index: %d (%s)\n",
       fusion_world_index(world), __FUNCTION__);
   printf("Am I the master? ");
   fusion_master(world) ? printf("Yes") : printf("No");
   printf(" (%s)\n", __FUNCTION__);

   printf("\tJoin Arena (%s)\n", __FUNCTION__);
   fusion_arena_enter(world, "WM Arena", NULL, join, &ctx, &arena, &ret);

   printf("\n\tPress enter to finish\n");
   read(1, &c, 1);

   printf("\tLeave Arena (%s)\n", __FUNCTION__);
   fusion_arena_exit(arena, NULL, leave, &ctx, 0, &ret);

   printf("Exit Fusion world (%s)\n", __FUNCTION__);
   fusion_exit(world, 0);

   return 0;
}

Compiling and running

For compiling both programs use :

gcc -Wall -O2 `pkg-config --cflags --libs fusion` fusionee_master.c -o fusionee_master
gcc -Wall -O2 `pkg-config --cflags --libs fusion` fusionee_slave.c -o fusionee_slave

The environment variable $PKG_CONFIG_PATH must be set to something like ${INSTALL_PATH}/lib/pkgconfig

Now run fusionee_master on a terminal then fusionee_slave on another. You can run the client as many times as you want, until you press enter on the terminal runing fusionee_master.



Return to Fusion:Examples