/**
@file
@brief 'exit' event
@details Copyright (c) 2017-2021 Acronis International GmbH
@author Mikhail Krivtsov (mikhail.krivtsov@acronis.com)
@since $Id: $
*/
#include "exit_event.h"
#include "debug.h"
#include "message.h"
#include "si_templates.h"
#include "si_writer_common.h"
#include "task_info_map.h"
static const uint8_t k_exit_fields[] = {
SI_COMMON_FIELDS,
};
static void exit_event_with_alloc_flags(struct task_struct* tsk, bool nowait)
{
msg_t* msg;
const uint32_t msg_size = SI_ESTIMATE_SIZE_CONST_PARAMS(k_exit_fields);
pid_t pid = tsk->pid;
pid_t tgid = tsk->tgid;
uint64_t unique_pid = make_unique_pid(tsk);
msg = msg_new_with_alloc_flags(FP_SI_OT_NOTIFY_PROCESS_EXIT, 0, SI_CT_POST_CALLBACK, unique_pid, msg_size, nowait);
if (msg) {
si_property_writer_t writer;
task_info_t* task_info = task_info_lookup(tgid, unique_pid);
uint64_t event_uid = transport_global_sequence_next();
si_event_writer_init(&writer, &msg->event, msg_size);
si_property_writer_write_common(&writer, event_uid, pid, tgid, task_info);
si_event_writer_finalize(&msg->event, &writer);
if (task_info) {
task_info_put(task_info);
}
send_msg_async(msg);
msg_unref(msg);
}
// This is not a strong guarantee that all other threads has exited but
// it is as close as kernel can provide to us.
if (tgid == pid)
task_info_map_on_exit_event(tsk);
}
void exit_event_nowait(struct task_struct* tsk)
{
return exit_event_with_alloc_flags(tsk, true /*nowait*/);
}
void exit_event(struct task_struct* tsk)
{
return exit_event_with_alloc_flags(tsk, false /*nowait*/);
}
|