Skip to content

Commit

Permalink
Merge pull request openucx#3709 from hoopoepg/topic/fix-for-test-even…
Browse files Browse the repository at this point in the history
…ts-v1.6

UCM/EVENT: fixed ucp_test_event call - v1.6
  • Loading branch information
yosefe authored Jun 17, 2019
2 parents 89ac0f3 + 1e1bfd1 commit 43afe2e
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 56 deletions.
16 changes: 0 additions & 16 deletions src/ucm/event/event.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,6 @@
#include <errno.h>


#define UCM_NATIVE_EVENT_VM_MAPPED (UCM_EVENT_MMAP | UCM_EVENT_MREMAP | \
UCM_EVENT_SHMAT | UCM_EVENT_SBRK)

#define UCM_NATIVE_EVENT_VM_UNMAPPED (UCM_EVENT_MMAP | UCM_EVENT_MUNMAP | \
UCM_EVENT_MREMAP | UCM_EVENT_SHMDT | \
UCM_EVENT_SHMAT | UCM_EVENT_SBRK | \
UCM_EVENT_MADVISE)

UCS_LIST_HEAD(ucm_event_installer_list);

static pthread_spinlock_t ucm_kh_lock;
Expand Down Expand Up @@ -600,14 +592,6 @@ ucs_status_t ucm_test_events(int events)
{
int out_events;

if (events & UCM_EVENT_VM_MAPPED) {
events |= UCM_NATIVE_EVENT_VM_MAPPED;
}

if (events & UCM_EVENT_VM_UNMAPPED) {
events |= UCM_NATIVE_EVENT_VM_UNMAPPED;
}

return ucm_mmap_test_events(events, &out_events);
}

Expand Down
7 changes: 7 additions & 0 deletions src/ucm/event/event.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@
#include <ucs/datastruct/list.h>
#include <ucs/type/status.h>

#define UCM_NATIVE_EVENT_VM_MAPPED (UCM_EVENT_MMAP | UCM_EVENT_MREMAP | \
UCM_EVENT_SHMAT | UCM_EVENT_SBRK)

#define UCM_NATIVE_EVENT_VM_UNMAPPED (UCM_EVENT_MMAP | UCM_EVENT_MUNMAP | \
UCM_EVENT_MREMAP | UCM_EVENT_SHMDT | \
UCM_EVENT_SHMAT | UCM_EVENT_SBRK)


typedef struct ucm_event_handler {
ucs_list_link_t list;
Expand Down
111 changes: 82 additions & 29 deletions src/ucm/mmap/install.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <ucm/bistro/bistro.h>
#include <ucs/sys/math.h>
#include <ucs/sys/checker.h>
#include <ucs/arch/bitops.h>
#include <ucs/debug/assert.h>

#include <sys/mman.h>
Expand All @@ -32,6 +33,13 @@
#define UCM_HOOK_STR \
((ucm_mmap_hook_mode() == UCM_MMAP_HOOK_RELOC) ? "reloc" : "bistro")

#define UCM_FIRE_EVENT(_event, _mask, _data, _call) \
do { \
(_data)->fired_events = 0; \
_call; \
(_data)->out_events &= ~((_event) & (_mask)) | (_data)->fired_events; \
} while(0)

extern const char *ucm_mmap_hook_modes[];

typedef enum ucm_mmap_hook_type {
Expand All @@ -47,6 +55,11 @@ typedef struct ucm_mmap_func {
ucm_mmap_hook_type_t hook_type;
} ucm_mmap_func_t;

typedef struct ucm_mmap_test_events_data {
int fired_events;
int out_events;
} ucm_mmap_test_events_data_t;

static ucm_mmap_func_t ucm_mmap_funcs[] = {
{ {"mmap", ucm_override_mmap}, UCM_EVENT_MMAP, 0, UCM_HOOK_BOTH},
{ {"munmap", ucm_override_munmap}, UCM_EVENT_MUNMAP, 0, UCM_HOOK_BOTH},
Expand All @@ -62,68 +75,108 @@ static ucm_mmap_func_t ucm_mmap_funcs[] = {
};

static void ucm_mmap_event_test_callback(ucm_event_type_t event_type,
ucm_event_t *event, void *arg)
ucm_event_t *event, void *fired_events)
{
int *out_events = arg;

*out_events |= event_type;
*(int*)fired_events |= event_type;
}

void ucm_fire_mmap_events(int events)
/* Fire events with pre/post action. The problem is in call sequence: we
* can't just fire single event - most of the system calls require set of
* calls to eliminate resource leaks or data corruption, such sequence
* produces additional events which may affect to event handling. To
* exclude additional events from processing used pre/post actions where
* set of handled events is cleared and evaluated for every system call */
static void
ucm_fire_mmap_events_internal(int events, ucm_mmap_test_events_data_t *data)
{
int shmid;
void *p;

if (events & (UCM_EVENT_MMAP|UCM_EVENT_MUNMAP|UCM_EVENT_MREMAP|
UCM_EVENT_VM_MAPPED|UCM_EVENT_VM_UNMAPPED)) {
p = mmap(NULL, 0, 0, 0, -1 ,0);
p = mremap(p, 0, 0, 0);
munmap(p, 0);
UCM_FIRE_EVENT(events, UCM_EVENT_MMAP|UCM_EVENT_VM_MAPPED,
data, p = mmap(NULL, ucm_get_page_size(), PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
/* generate MAP event */
UCM_FIRE_EVENT(events, UCM_EVENT_MREMAP|UCM_EVENT_VM_MAPPED|UCM_EVENT_VM_UNMAPPED,
data, p = mremap(p, ucm_get_page_size(),
ucm_get_page_size() * 2, MREMAP_MAYMOVE));
/* generate UNMAP event */
UCM_FIRE_EVENT(events, UCM_EVENT_MREMAP|UCM_EVENT_VM_MAPPED|UCM_EVENT_VM_UNMAPPED,
data, p = mremap(p, ucm_get_page_size() * 2, ucm_get_page_size(), 0));
/* generate UNMAP event */
UCM_FIRE_EVENT(events, UCM_EVENT_MMAP|UCM_EVENT_VM_MAPPED,
data, p = mmap(p, ucm_get_page_size(), PROT_READ | PROT_WRITE,
MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
UCM_FIRE_EVENT(events, UCM_EVENT_MUNMAP|UCM_EVENT_VM_UNMAPPED,
data, munmap(p, ucm_get_page_size()));
}

if (events & (UCM_EVENT_SHMAT|UCM_EVENT_SHMDT|UCM_EVENT_VM_MAPPED|UCM_EVENT_VM_UNMAPPED)) {
p = shmat(0, NULL, 0);
shmdt(p);
shmid = shmget(IPC_PRIVATE, ucm_get_page_size(), IPC_CREAT | SHM_R | SHM_W);
if (shmid == -1) {
ucm_debug("shmget failed: %m");
return;
}

UCM_FIRE_EVENT(events, UCM_EVENT_SHMAT|UCM_EVENT_VM_MAPPED,
data, p = shmat(shmid, NULL, 0));
UCM_FIRE_EVENT(events, UCM_EVENT_SHMAT|UCM_EVENT_VM_MAPPED|UCM_EVENT_VM_UNMAPPED,
data, p = shmat(shmid, p, SHM_REMAP));
shmctl(shmid, IPC_RMID, NULL);
UCM_FIRE_EVENT(events, UCM_EVENT_SHMDT|UCM_EVENT_VM_UNMAPPED,
data, shmdt(p));
}

if (events & (UCM_EVENT_SBRK|UCM_EVENT_VM_MAPPED|UCM_EVENT_VM_UNMAPPED)) {
(void)sbrk(ucm_get_page_size());
(void)sbrk(-ucm_get_page_size());
UCM_FIRE_EVENT(events, UCM_EVENT_SBRK|UCM_EVENT_VM_MAPPED,
data, (void)sbrk(ucm_get_page_size()));
UCM_FIRE_EVENT(events, UCM_EVENT_SBRK|UCM_EVENT_VM_UNMAPPED,
data, (void)sbrk(-ucm_get_page_size()));
}

if (events & UCM_EVENT_MADVISE) {
p = mmap(NULL, ucm_get_page_size(), PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANON, -1, 0);
UCM_FIRE_EVENT(events, UCM_EVENT_MMAP|UCM_EVENT_VM_MAPPED, data,
p = mmap(NULL, ucm_get_page_size(), PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANON, -1, 0));
if (p != MAP_FAILED) {
madvise(p, ucm_get_page_size(), MADV_NORMAL);
munmap(p, ucm_get_page_size());
UCM_FIRE_EVENT(events, UCM_EVENT_MADVISE, data,
madvise(p, ucm_get_page_size(), MADV_NORMAL));
UCM_FIRE_EVENT(events, UCM_EVENT_MUNMAP|UCM_EVENT_VM_UNMAPPED, data,
munmap(p, ucm_get_page_size()));
} else {
ucm_debug("mmap failed: %m");
}
}
}

void ucm_fire_mmap_events(int events)
{
ucm_mmap_test_events_data_t data;

ucm_fire_mmap_events_internal(events, &data);
}

ucs_status_t ucm_mmap_test_events(int events, int *out_events)
{
ucm_event_handler_t handler;
ucm_mmap_test_events_data_t data;

/* Install a temporary event handler which will add the supported event
* type to out_events bitmap.
*/
handler.events = events;
handler.priority = -1;
handler.cb = ucm_mmap_event_test_callback;
handler.arg = out_events;
*out_events = 0;
handler.events = events;
handler.priority = -1;
handler.cb = ucm_mmap_event_test_callback;
handler.arg = &data.fired_events;
data.out_events = events;

ucm_event_handler_add(&handler);

ucm_fire_mmap_events(events);

ucm_fire_mmap_events_internal(events, &data);
ucm_event_handler_remove(&handler);

*out_events = data.out_events;

ucm_debug("mmap test: got 0x%x out of 0x%x", *out_events, events);

/* Return success iff we caught all wanted events */
/* Return success if we caught all wanted events */
if (!ucs_test_all_flags(*out_events, events)) {
return UCS_ERR_UNSUPPORTED;
}
Expand All @@ -135,7 +188,7 @@ ucs_status_t ucm_mmap_test_events(int events, int *out_events)
static ucs_status_t ucm_mmap_test(int events)
{
static int installed_events = 0;
int out_events;
int out_events = 0; /* GCC bug: it reports compilation fail if not initialized */
ucs_status_t status;

if (ucs_test_all_flags(installed_events, events)) {
Expand Down
66 changes: 55 additions & 11 deletions test/gtest/ucm/malloc_hook.cc
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,26 @@ class mmap_event {
class malloc_hook : public ucs::test {
friend class mmap_event<malloc_hook>;
protected:
/* use template argument to call/not call vm_unmap handler */
/* GCC 4.4.7 doesn't allow to define template static function
* with integer template argument. using template inner class
* to define static function */
template <int C> class bistro_hook {
public:
static int munmap(void *addr, size_t length)
{
UCM_BISTRO_PROLOGUE;
malloc_hook::bistro_call_counter++;
if (C) {
/* notify aggregate vm_munmap event only */
ucm_vm_munmap(addr, length);
}
int res = (intptr_t)syscall(SYS_munmap, addr, length);
UCM_BISTRO_EPILOGUE;
return res;
}
};

void mem_event(ucm_event_type_t event_type, ucm_event_t *event)
{
m_got_event = 1;
Expand Down Expand Up @@ -142,15 +162,6 @@ class malloc_hook : public ucs::test {
event.unset();
}

static int bistro_munmap_hook(void *addr, size_t length)
{
UCM_BISTRO_PROLOGUE;
bistro_call_counter++;
int res = (intptr_t)syscall(SYS_munmap, addr, length);
UCM_BISTRO_EPILOGUE;
return res;
}

void skip_on_bistro() {
/* BISTRO is disabled under valgrind, we may run tests */
if ((ucm_global_opts.mmap_hook_mode == UCM_MMAP_HOOK_BISTRO) &&
Expand Down Expand Up @@ -927,7 +938,7 @@ UCS_TEST_F(malloc_hook, bistro_patch) {
}

/* set hook to mmap call */
status = ucm_bistro_patch(symbol, (void*)bistro_munmap_hook, &rp);
status = ucm_bistro_patch(symbol, (void*)bistro_hook<0>::munmap, &rp);
ASSERT_UCS_OK(status);
EXPECT_NE((intptr_t)rp, NULL);

Expand Down Expand Up @@ -1000,7 +1011,7 @@ UCS_TEST_F(malloc_hook, test_event_failed) {
ASSERT_UCS_OK(status);

/* set hook to mmap call */
status = ucm_bistro_patch(symbol, (void*)bistro_munmap_hook, &rp);
status = ucm_bistro_patch(symbol, (void*)bistro_hook<0>::munmap, &rp);
ASSERT_UCS_OK(status);
EXPECT_NE((intptr_t)rp, NULL);

Expand All @@ -1015,6 +1026,39 @@ UCS_TEST_F(malloc_hook, test_event_failed) {
ASSERT_UCS_OK(status);
}

UCS_TEST_F(malloc_hook, test_event_unmap) {
mmap_event<malloc_hook> event(this);
ucs_status_t status;
const char *symbol = "munmap";
ucm_bistro_restore_point_t *rp = NULL;

if (RUNNING_ON_VALGRIND) {
UCS_TEST_SKIP_R("skipping on valgrind");
}

if (ucm_global_opts.mmap_hook_mode != UCM_MMAP_HOOK_BISTRO) {
UCS_TEST_SKIP_R("skipping on non-BISTRO hooks");
}

status = event.set(UCM_EVENT_MUNMAP);
ASSERT_UCS_OK(status);

/* set hook to mmap call */
status = ucm_bistro_patch(symbol, (void*)bistro_hook<1>::munmap, &rp);
ASSERT_UCS_OK(status);
EXPECT_NE((intptr_t)rp, NULL);

status = ucm_test_events(UCM_EVENT_MUNMAP);
EXPECT_TRUE(status == UCS_ERR_UNSUPPORTED);

status = ucm_test_events(UCM_EVENT_VM_UNMAPPED);
EXPECT_TRUE(status == UCS_OK);

/* restore original mmap body */
status = ucm_bistro_restore(rp);
ASSERT_UCS_OK(status);
}

/* test for mmap events are fired from non-direct load modules
* we are trying to load lib1, from lib1 load lib2, and
* fire mmap event from lib2 */
Expand Down

0 comments on commit 43afe2e

Please sign in to comment.