+static int
+op_add_code(struct oprofile_cpu_buffer *cpu_buf, unsigned long backtrace,
+ int is_kernel, struct task_struct *task)
+{
+ struct op_entry entry;
+ struct op_sample *sample;
+ unsigned long flags;
+ int size;
+
+ flags = 0;
+
+ if (backtrace)
+ flags |= TRACE_BEGIN;
+
+ /* notice a switch from user->kernel or vice versa */
+ is_kernel = !!is_kernel;
+ if (cpu_buf->last_is_kernel != is_kernel) {
+ cpu_buf->last_is_kernel = is_kernel;
+ flags |= KERNEL_CTX_SWITCH;
+ if (is_kernel)
+ flags |= IS_KERNEL;
+ }
+
+ /* notice a task switch */
+ if (cpu_buf->last_task != task) {
+ cpu_buf->last_task = task;
+ flags |= USER_CTX_SWITCH;
+ }
+
+ if (!flags)
+ /* nothing to do */
+ return 0;
+
+ if (flags & USER_CTX_SWITCH)
+ size = 1;
+ else
+ size = 0;
+
+ sample = op_cpu_buffer_write_reserve(&entry, size);
+ if (!sample)
+ return -ENOMEM;
+
+ sample->eip = ESCAPE_CODE;
+ sample->event = flags;
+
+ if (size)
+ sample->data[0] = (unsigned long)task;
+
+ op_cpu_buffer_write_commit(&entry);
+
+ return 0;
+}
+