Пример #1
0
CP_HIDDEN void cpi_wait_mutex(cpi_mutex_t *mutex) {
	DWORD self = GetCurrentThreadId();

	assert(mutex != NULL);
	lock_mutex(mutex->os_mutex);
	if (mutex->lock_count > 0
		&& self == mutex->os_thread) {
		int lc = mutex->lock_count;

		// Release mutex
		mutex->lock_count = 0;
		mutex->num_wait_threads++;
		set_event(mutex->os_cond_lock);
		unlock_mutex(mutex->os_mutex);

		// Wait for signal
		wait_for_event(mutex->os_cond_wake);

		// Reset wake signal if last one waking up
		lock_mutex(mutex->os_mutex);
		if (--mutex->num_wait_threads == 0) {
			reset_event(mutex->os_cond_wake);
		}

		// Re-acquire mutex and restore lock count for this thread
		lock_mutex_holding(mutex);
		mutex->lock_count = lc;

	} else {
		cpi_fatalf(_("Internal C-Pluff error: Unauthorized attempt at waiting on a mutex."));
	}
	unlock_mutex(mutex->os_mutex);
}
Пример #2
0
static void wait_for_event(HANDLE event) {
	if (WaitForSingleObject(event, INFINITE) != WAIT_OBJECT_0) {
		char buffer[256];
		DWORD ec = GetLastError();
		cpi_fatalf(_("Could not wait for an event due to error %ld: %s"),
			(long) ec, get_win_errormsg(ec, buffer, sizeof(buffer)));
	}
}
Пример #3
0
static void reset_event(HANDLE event) {
	if (!ResetEvent(event)) {
		char buffer[256];
		DWORD ec = GetLastError();
		cpi_fatalf(_("Could not reset an event due to error %ld: %s"),
			(long) ec, get_win_errormsg(ec, buffer, sizeof(buffer)));
	}
}
Пример #4
0
static void unlock_mutex(HANDLE mutex) {
	if (!ReleaseMutex(mutex)) {
		char buffer[256];
		DWORD ec = GetLastError();
		cpi_fatalf(_("Could not release a mutex due to error %ld: %s"),
			(long) ec, get_win_errormsg(ec, buffer, sizeof(buffer)));
	}
}
Пример #5
0
CP_C_API cp_status_t cp_define_symbol(cp_context_t *context, const char *name, void *ptr) {
    cp_status_t status = CP_OK;

    CHECK_NOT_NULL(context);
    CHECK_NOT_NULL(name);
    CHECK_NOT_NULL(ptr);
    if (context->plugin == NULL) {
        cpi_fatalf(_("Only plug-ins can define context specific symbols."));
    }

    cpi_lock_context(context);
    cpi_check_invocation(context, CPI_CF_LOGGER | CPI_CF_LISTENER, __func__);
    do {
        char *n;

        // Create a symbol hash if necessary
        if (context->plugin->defined_symbols == NULL) {
            if ((context->plugin->defined_symbols = hash_create(HASHCOUNT_T_MAX, (int (*)(const void *, const void *)) strcmp, NULL)) == NULL) {
                status = CP_ERR_RESOURCE;
                break;
            }
        }

        // Check for a previously defined symbol
        if (hash_lookup(context->plugin->defined_symbols, name) != NULL) {
            status = CP_ERR_CONFLICT;
            break;
        }

        // Insert the symbol into the symbol hash
        n = strdup(name);
        if (n == NULL || !hash_alloc_insert(context->plugin->defined_symbols, n, ptr)) {
            free(n);
            status = CP_ERR_RESOURCE;
            break;
        }

    } while (0);

    // Report error
    if (status != CP_OK) {
        switch (status) {
        case CP_ERR_RESOURCE:
            cpi_errorf(context, N_("Plug-in %s could not define symbol %s due to insufficient memory."), context->plugin->plugin->identifier, name);
            break;
        case CP_ERR_CONFLICT:
            cpi_errorf(context, N_("Plug-in %s tried to redefine symbol %s."), context->plugin->plugin->identifier, name);
            break;
        default:
            break;
        }
    }
    cpi_unlock_context(context);

    return status;
}
Пример #6
0
static void lock_mutex(HANDLE mutex) {
	DWORD ec;

	if ((ec = WaitForSingleObject(mutex, INFINITE)) != WAIT_OBJECT_0) {
		char buffer[256];
		ec = GetLastError();
		cpi_fatalf(_("Could not lock a mutex due to error %ld: %s"),
			(long) ec, get_win_errormsg(ec, buffer, sizeof(buffer)));
	}
}
Пример #7
0
CP_HIDDEN void cpi_check_invocation(cp_context_t *ctx, int funcmask, const char *func) {
	assert(ctx != NULL);
	assert(funcmask != 0);
	assert(func != NULL);
	assert(cpi_is_context_locked(ctx));
	if ((funcmask & CPI_CF_LOGGER)
		&&ctx->env->in_logger_invocation) {
		cpi_fatalf(_("Function %s was called from within a logger invocation."), func);
	}
	if ((funcmask & CPI_CF_LISTENER)
		&& ctx->env->in_event_listener_invocation) {
		cpi_fatalf(_("Function %s was called from within an event listener invocation."), func);
	}
	if ((funcmask & CPI_CF_START)
		&& ctx->env->in_start_func_invocation) {
		cpi_fatalf(_("Function %s was called from within a plug-in start function invocation."), func);
	}
	if ((funcmask & CPI_CF_STOP)
		&& ctx->env->in_stop_func_invocation) {
		cpi_fatalf(_("Function %s was called from within a plug-in stop function invocation."), func);
	}
	if (ctx->env->in_create_func_invocation) {
		cpi_fatalf(_("Function %s was called from within a plug-in create function invocation."), func);
	}
	if (ctx->env->in_destroy_func_invocation) {
		cpi_fatalf(_("Function %s was called from within a plug-in destroy function invocation."), func);
	}
}
Пример #8
0
CP_HIDDEN void cpi_signal_mutex(cpi_mutex_t *mutex) {
	DWORD self = GetCurrentThreadId();

	assert(mutex != NULL);
	lock_mutex(mutex->os_mutex);
	if (mutex->lock_count > 0
		&& self == mutex->os_thread) {
		set_event(mutex->os_cond_wake);
	} else {
		cpi_fatalf(_("Internal C-Pluff error: Unauthorized attempt at signaling a mutex."));
	}
	unlock_mutex(mutex->os_mutex);
}
Пример #9
0
CP_C_API void cp_log(cp_context_t *context, cp_log_severity_t severity, const char *msg) {
	CHECK_NOT_NULL(context);
	CHECK_NOT_NULL(msg);
	cpi_lock_context(context);
	cpi_check_invocation(context, CPI_CF_LOGGER, __func__);
	if (severity < CP_LOG_DEBUG || severity > CP_LOG_ERROR) {
		cpi_fatalf(_("Illegal severity value in call to %s."), __func__);
	}
	if (cpi_is_logged(context, severity)) {
		do_log(context, severity, msg);
	}
	cpi_unlock_context(context);
}
Пример #10
0
CP_C_API void cp_set_context_args(cp_context_t *ctx, char **argv) {
	int argc;
	
	CHECK_NOT_NULL(ctx);
	CHECK_NOT_NULL(argv);
	for (argc = 0; argv[argc] != NULL; argc++);
	if (argc < 1) {
		cpi_fatalf(_("At least one startup argument must be given in call to function %s."), __func__);
	}
	cpi_lock_context(ctx);
	ctx->env->argc = argc;
	ctx->env->argv = argv;
	cpi_unlock_context(ctx);
}
Пример #11
0
CP_C_API void cp_destroy_context(cp_context_t *context) {
	CHECK_NOT_NULL(context);
	if (context->plugin != NULL) {
		cpi_fatalf(_("Only the main program can destroy a plug-in context."));
	}

	// Check invocation
	cpi_lock_context(context);
	cpi_check_invocation(context, CPI_CF_ANY, __func__);
	cpi_unlock_context(context);

#ifdef CP_THREADS
	assert(context->env->mutex == NULL || !cpi_is_mutex_locked(context->env->mutex));
#else
	assert(!context->env->locked);
#endif

	// Remove context from the context list
	cpi_lock_framework();
	if (contexts != NULL) {
		lnode_t *node;
		
		if ((node = list_find(contexts, context, cpi_comp_ptr)) != NULL) {
			list_delete(contexts, node);
			lnode_destroy(node);
		}
	}
	cpi_unlock_framework();

	// Unload all plug-ins 
	cp_uninstall_plugins(context);
	
	// Unregister all plug-in loaders
	cp_unregister_ploaders(context);
	
	// Unregister implicit local plug-in loader, if any
	if (context->env->local_loader != NULL) {
		cp_unregister_ploader(context, context->env->local_loader);
	}

	// Release remaining information objects
	cpi_release_infos(context);
	
	// Free context
	cpi_free_context(context);
}
Пример #12
0
static void do_log(cp_context_t *context, cp_log_severity_t severity, const char *msg) {
	lnode_t *node;
	const char *apid = NULL;

	assert(cpi_is_context_locked(context));	
	if (context->env->in_logger_invocation) {
		cpi_fatalf(_("Encountered a recursive logging request within a logger invocation."));
	}
	if (context->plugin != NULL) {
		apid = context->plugin->plugin->identifier;
	}
	context->env->in_logger_invocation++;
	node = list_first(context->env->loggers);
	while (node != NULL) {
		logger_t *lh = lnode_get(node);
		if (severity >= lh->min_severity) {
			lh->logger(severity, msg, apid, lh->user_data);
		}
		node = list_next(context->env->loggers, node);
	}
	context->env->in_logger_invocation--;
}