1 ////////////////////////////////////////////////////////////////////////////////////
6 // This file is C++ source for SWAP driver.
9 // AUTHOR: L.Komkov, A.Gerenkov
10 // COMPANY NAME: Samsung Research Center in Moscow
11 // DEPT NAME: Advanced Software Group
12 // CREATED: 2008.02.15
14 // REVISION DATE: 2008.12.03
16 ////////////////////////////////////////////////////////////////////////////////////
21 ////////////////////////////////////////////////////////////////////////////////////////////
24 .ec_state = EC_STATE_IDLE,
26 .buffer_size = EC_BUFFER_SIZE_DEFAULT,
27 .ignored_events_count = 0,
30 ////////////////////////////////////////////////////////////////////////////////////////////
32 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38)
33 spinlock_t ec_spinlock; // protects 'ec_info'
34 #else /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38) */
35 spinlock_t ec_spinlock = SPIN_LOCK_UNLOCKED;
36 #endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38) */
38 ec_probe_info_t ec_probe_info = {
46 ec_state_t GetECState(void) { return ec_info.ec_state; };
48 void reset_ec_info_nolock(void)
50 ec_info.trace_size = 0;
52 ec_info.after_last = 0;
53 ec_info.ignored_events_count = 0;
54 ec_info.saved_events_count = 0;
55 ec_info.discarded_events_count = 0;
56 ec_info.collision_count = 0;
57 ec_info.lost_events_count = 0;
60 void ResetECInfo(void)
62 unsigned long spinlock_flags = 0L;
64 spin_lock_irqsave (&ec_spinlock, spinlock_flags);
65 reset_ec_info_nolock();
66 spin_unlock_irqrestore (&ec_spinlock, spinlock_flags);
69 void CleanECInfo(void)
71 unsigned long spinlock_flags = 0L;
73 spin_lock_irqsave (&ec_spinlock, spinlock_flags);
74 ec_info.buffer_effect = 0;
75 spin_unlock_irqrestore (&ec_spinlock, spinlock_flags);
81 int IsECMode(unsigned long nMask)
83 return ((ec_info.m_nMode & nMask) != 0);
86 int IsContinuousRetrieval(void)
88 return IsECMode(MODEMASK_CONTINUOUS_RETRIEVAL);
91 int SetECMode(unsigned long nECMode)
93 unsigned long spinlock_flags = 0L;
95 if((nECMode & MODEMASK_CONTINUOUS_RETRIEVAL) != 0) {
96 if(EnableContinuousRetrieval() == -1) {
97 EPRINTF("Cannot enable continuous retrieval!");
101 if(DisableContinuousRetrieval() == -1) {
102 EPRINTF("Cannot disable continuous retrieval!");
107 spin_lock_irqsave (&ec_spinlock, spinlock_flags);
108 ec_info.m_nMode = nECMode;
109 reset_ec_info_nolock();
110 spin_unlock_irqrestore (&ec_spinlock, spinlock_flags);
115 unsigned long GetECMode(void)
117 unsigned long ec_mode;
118 unsigned long spinlock_flags = 0L;
120 spin_lock_irqsave(&ec_spinlock, spinlock_flags);
121 ec_mode = ec_info.m_nMode;
122 spin_unlock_irqrestore(&ec_spinlock, spinlock_flags);
127 int is_java_inst_enabled(void)
129 return !!(GetECMode() & MODEMASK_JAVA_INST);
133 static UNUSED char * ec_state_name (ec_state_t ec_state)
135 static char *ec_state_names[EC_STATE_TAG_COUNT] = { "IDLE", "ATTACHED", "ACTIVE", "STOPPED" };
137 if (((unsigned) ec_info.ec_state) < EC_STATE_TAG_COUNT)
139 return ec_state_names[ec_info.ec_state];
146 #endif /* defined(__DEBUG) */
150 On user request user space EC may change state in the following order:
151 IDLE -> ATTACHED (on "attach")
152 IDLE | ATTACHED -> ACTIVE (on "activate")
153 ATTACHED | ACTIVE | STOPPED -> IDLE (on "stop"/"detach")
155 int ec_user_attach (void)
157 unsigned long spinlock_flags;
160 spin_lock_irqsave (&ec_spinlock, spinlock_flags); // make other CPUs wait
161 if (EC_STATE_IDLE == ec_info.ec_state)
166 struct event_tmpl *p_tmpl;
168 ec_info.ec_state = EC_STATE_ATTACHED;
170 /* save 'start' time */
171 do_gettimeofday(&tv);
172 memcpy(&last_attach_time, &tv, sizeof(struct timeval));
174 /* unpause if paused */
177 /* if there is at least one start condition in the list
178 we are paused at the beginning */
179 list_for_each_entry(p_cond, &cond_list.list, list) {
180 p_tmpl = &p_cond->tmpl;
181 if (p_tmpl->type == ET_TYPE_START_COND) {
187 spin_unlock_irqrestore (&ec_spinlock, spinlock_flags); // open our data for other CPUs
189 //first of all put event with event format
192 pack_event_info(EVENT_FMT_PROBE_ID, RECORD_ENTRY, "x", tmp);
195 result = inst_usr_space_proc();
196 if (result == 0) // instrument user space process
197 result = set_kernel_probes();
198 // FIXME: SAFETY CHECK
200 { // return to safe state
201 unset_kernel_probes();
203 spin_lock_irqsave (&ec_spinlock, spinlock_flags); // make other CPUs wait
204 ec_info.ec_state = EC_STATE_IDLE;
205 spin_unlock_irqrestore (&ec_spinlock, spinlock_flags); // open our data for other CPUs
207 // FIXME: SAFETY CHECK
209 notify_user (EVENT_EC_STATE_CHANGE);
215 spin_unlock_irqrestore (&ec_spinlock, spinlock_flags); // open our data for other CPUs
223 int ec_user_activate (void)
225 unsigned long spinlock_flags;
228 spin_lock_irqsave (&ec_spinlock, spinlock_flags); // make other CPUs wait
229 if (EC_STATE_IDLE == ec_info.ec_state)
232 ec_info.ec_state = EC_STATE_ACTIVE;
233 spin_unlock_irqrestore (&ec_spinlock, spinlock_flags); // open our data for other CPUs
234 //first of all put event with event format
237 pack_event_info(EVENT_FMT_PROBE_ID, RECORD_ENTRY, "x", tmp);
240 result = inst_usr_space_proc();
241 if (result == 0) // instrument user space process
242 result = set_kernel_probes();
244 // FIXME: SAFETY CHECK
246 { // return to safe state
247 unset_kernel_probes();
249 spin_lock_irqsave (&ec_spinlock, spinlock_flags); // make other CPUs wait
250 ec_info.ec_state = EC_STATE_IDLE;
251 spin_unlock_irqrestore (&ec_spinlock, spinlock_flags); // open our data for other CPUs
253 // FIXME: SAFETY CHECK
255 notify_user (EVENT_EC_STATE_CHANGE);
258 else if (EC_STATE_ATTACHED == ec_info.ec_state)
261 ec_info.ec_state = EC_STATE_ACTIVE;
263 spin_unlock_irqrestore (&ec_spinlock, spinlock_flags); // open our data for other CPUs
265 notify_user (EVENT_EC_STATE_CHANGE);
271 spin_unlock_irqrestore (&ec_spinlock, spinlock_flags); // open our data for other CPUs
278 int ec_user_stop (void)
280 unsigned long spinlock_flags;
281 int result = 0, ret = 0;
283 spin_lock_irqsave (&ec_spinlock, spinlock_flags); // make other CPUs wait
284 if (EC_STATE_ATTACHED == ec_info.ec_state || EC_STATE_ACTIVE == ec_info.ec_state || EC_STATE_STOPPED == ec_info.ec_state)
287 ec_info.ec_state = EC_STATE_IDLE;
288 spin_unlock_irqrestore (&ec_spinlock, spinlock_flags); // open our data for other CPUs
290 ret = deinst_usr_space_proc ();
291 result = unset_kernel_probes();
295 notify_user (EVENT_EC_STATE_CHANGE);
301 spin_unlock_irqrestore (&ec_spinlock, spinlock_flags); // open our data for other CPUs
310 Kernel space EC may change state in the following order:
311 ATTACHED -> ACTIVE (when start condition is satisfied)
312 ACTIVE -> STOPPED (when stop condition is satisfied)
314 int ec_kernel_activate (void)
316 unsigned long spinlock_flags;
319 spin_lock_irqsave (&ec_spinlock, spinlock_flags); // make other CPUs wait
320 if (EC_STATE_ATTACHED == ec_info.ec_state)
322 ec_info.ec_state = EC_STATE_ACTIVE;
329 spin_unlock_irqrestore (&ec_spinlock, spinlock_flags); // open our data for other CPUs
331 notify_user (EVENT_EC_STATE_CHANGE);
336 int ec_kernel_stop (void)
338 unsigned long spinlock_flags;
341 spin_lock_irqsave (&ec_spinlock, spinlock_flags); // make other CPUs wait
342 if (EC_STATE_ACTIVE == ec_info.ec_state)
344 ec_info.ec_state = EC_STATE_STOPPED;
351 spin_unlock_irqrestore (&ec_spinlock, spinlock_flags); // open our data for other CPUs
353 notify_user (EVENT_EC_STATE_CHANGE);
358 // Copies EC info to user space
359 // Since "copy_to_user" may block, an intermediate copy of ec_info is used here
360 int copy_ec_info_to_user_space (ec_info_t * p_user_ec_info)
363 WARNING: to avoid stack overflow the following data structure was made
364 static. As result, simultaneous users of this function will share it
365 and must use additional synchronization to avoid collisions.
367 // FIXME: synchronization is necessary here (ec_info_copy must be locked).
368 static ec_info_t ec_info_copy;
369 unsigned long spinlock_flags;
372 // ENTER_CRITICAL_SECTION
373 // lock semaphore here
376 // ENTER_CRITICAL_SECTION
377 spin_lock_irqsave (&ec_spinlock, spinlock_flags); // make other CPUs wait
380 memcpy (&ec_info_copy, &ec_info, sizeof (ec_info_copy));
382 // LEAVE_CRITICAL_SECTION
383 spin_unlock_irqrestore (&ec_spinlock, spinlock_flags); // open our data for other CPUs
386 result = copy_to_user ((void __user *) p_user_ec_info, &ec_info_copy, sizeof (ec_info_t));
388 // LEAVE_CRITICAL_SECTION
389 // unlock semaphore here
393 EPRINTF ("copy_to_user(%08X,%08X)=%d", (unsigned) p_user_ec_info, (unsigned) &ec_info_copy, result);