// if create == 0: create new share-memory channel // else: attach exist share-memory channel and verify data bus_terminal_channel_t* bus_terminal_channel_init(int32_t shmkey, bus_addr_t from, bus_addr_t to, size_t size, int32_t create) { struct shm_t* shm; bus_terminal_channel_t* btc; size_t alloc_size = size + sizeof(bus_channel_t) + rbuffer_head_size(); // init terminal channel btc = (bus_terminal_channel_t*)MALLOC(sizeof(*btc)); if (!btc) { return NULL; } // share memory if (create == 0) { shm = shm_create(shmkey, alloc_size, 0); } else { shm = shm_create(shmkey, alloc_size, 1); } if (!shm) { FREE(btc); return NULL; } // init channel or verify channel data btc->bc = shm_mem(shm); assert(btc->bc); if (create == 0) { btc->bc->shmkey = shmkey; btc->bc->from = from; btc->bc->to = to; btc->bc->channel_size = size; } else { if (btc->bc->shmkey != shmkey || btc->bc->from != from || btc->bc->to != to || btc->bc->channel_size != size) { FREE(btc); return NULL; } } // init ring buffer btc->r = rbuffer_init_mem((char*)btc->bc + sizeof(bus_channel_t), btc->bc->channel_size + rbuffer_head_size()); if (!btc->r) { FREE(btc); return NULL; } return btc; }
int32_t _bus_terminal_init_create(bus_terminal_t* bt, int16_t key) { int32_t buskey = (key << 16); struct shm_t* shm = shm_create(buskey, sizeof(bus_t), 0); if (shm) { bt->bus = (bus_t*)shm_mem(shm); assert(bt->bus); bt->bus->key = buskey; bt->bus->channel_key = 0; bt->bus->size = sizeof(bus_t); // terminals local info bt->bus->terminal_count = 1; bt->bus->terminals[0] = bt->self; atom_set(&bt->bus->terminal_version, 1); // channels info bt->bus->channel_count = 0; atom_set(&bt->bus->channel_version, 1); return 0; } return -1; }
int32_t _bus_terminal_init_attach(bus_terminal_t* bt, int16_t key) { int32_t buskey = (key << 16); int32_t i; struct shm_t* shm; int32_t registered = -1; // attach exsit shm shm = shm_create(buskey, sizeof(bus_t), 1); if (!shm) { return -1; } bt->bus = (bus_t*)shm_mem(shm); // invalid shm data if (bt->bus->key != buskey || bt->bus->size != sizeof(bus_t)) { return -1; } // register terminal info for (i = 0; i < bt->bus->terminal_count; ++ i) { if (bt->bus->terminals[i] == bt->self) { registered = 0; break; } } if (registered != 0) { if (bt->bus->terminal_count >= BUS_MAX_TERMINAL_COUNT) { return -1; } else { bt->bus->terminals[bt->bus->terminal_count ++] = bt->self; atom_inc(&bt->bus->terminal_version); } } return 0; }