#include "vf_printk.h"
#include "vf_initexit.h"
#include "vf_mem.h"
#include "vf_procfs.h"
#include "vf_mutex.h"
#include "limits.h"
static int counter;
static struct vf_mutex *mutex;
static struct vf_procfs_dir *dir;
static struct vf_procfs_file *file;
/*@
predicate callback_data_mutexed() =
integer(&counter, ?counter_ptr);
@*/
/*@
predicate_family_instance
vf_procfs_read_callback_data(read_proc_callback)() =
pointer(&mutex, ?mutex_ptr)
&*& vf_mutex(mutex_ptr, callback_data_mutexed);
@*/
/*@
predicate module_state() =
pointer(&dir, ?dir_ptr)
&*& vf_procfs_dir(
dir_ptr,
cons(
'h',
cons('e',
cons('l',
cons('l',
cons('o',
cons('p',
cons('r',
cons('o',
cons('c',
cons('\0',
nil)))))))))
)
, 1
)
&*& pointer(&file, ?file_ptr)
&*& vf_procfs_file(
file_ptr,
cons(
'v',
cons('a',
cons('l',
cons('u',
cons('e',
cons('\0',
nil)))))
),
dir_ptr,
read_proc_callback
)
&*& vf_cleanup_debt(
1
+1
+1
);
@*/
int read_proc_callback(struct vf_procfs_callback_handle *cb_handle)
//@ : vf_procfs_read_callback_t
/*@ requires
[?fracData]vf_procfs_read_callback_data(
read_proc_callback)()
&*& [?fracHandle]vf_procfs_callback_handle(cb_handle)
&*& vf_procfs_read_callback_buffer(cb_handle, nil, _);
@*/
/*@ ensures
[fracData]vf_procfs_read_callback_data(
read_proc_callback)()
&*& [fracHandle]vf_procfs_callback_handle(cb_handle)
&*& vf_procfs_read_callback_buffer(cb_handle,
?cs,
?isFullUnknown)
&*& result == 0;
@*/
{
int counter_backup;
vf_procfs_put_string(cb_handle, "This is helloproc.\n");
vf_procfs_put_string(cb_handle, "This file is read ");
//@ open [fracData]vf_procfs_read_callback_data(read_proc_callback)();
vf_mutex_lock(mutex);
//@ open callback_data_mutexed();
counter_backup = counter;
if (counter < INT_MAX){
//@ produce_limits(counter);
counter++;
}else{
vf_procfs_put_string(cb_handle, "more than ");
}
vf_procfs_put_int(cb_handle, counter);
vf_procfs_put_string(cb_handle, " times.\n");
if (vf_procfs_is_buffer_full(cb_handle)){
counter = counter_backup;
}
//@ close callback_data_mutexed();
vf_mutex_unlock(mutex);
//@ close [fracData]vf_procfs_read_callback_data(read_proc_callback)();
return 0;
}
int helloproc_main_module_init() //@ : module_setup_t(helloproc_main)
//@ requires module(helloproc_main, true) &*& vf_cleanup_debt(0);
/*@ ensures
result == 0 ?
module_state()
:
module(helloproc_main, _)
&*& result == -1
&*& vf_cleanup_debt(0);
@*/
{
//@ open_module();
dir = vf_procfs_mkdir("helloproc");
if (dir == 0){
goto error_mkdir;
}
counter = 0;
//@ close callback_data_mutexed();
//@ close vf_mutex_create_ghost_arg(callback_data_mutexed);
mutex = vf_mutex_create();
if (mutex == 0){
goto error_mutex;
}
mutex = mutex;
//@ close vf_procfs_read_callback_data(read_proc_callback)();
file = vf_procfs_create_file("value", dir, read_proc_callback);
if (file == 0){
goto error_file;
}
//@ close module_state();
return 0;
error_file:
//@ open vf_procfs_read_callback_data(read_proc_callback)();
vf_mutex_dispose(mutex);
error_mutex:
//@ open callback_data_mutexed();
vf_procfs_rmdir(dir);
error_mkdir:
//@ close_module();
return -1;
}
void helloproc_main_module_exit() //@ : module_cleanup_t(helloproc_main)
//@ requires module_state();
//@ ensures module(helloproc_main, _) &*& vf_cleanup_debt(0);
{
//@ open module_state();
vf_procfs_remove_file(file, dir);
//@ open vf_procfs_read_callback_data(read_proc_callback)();
vf_mutex_dispose(mutex);
//@ open callback_data_mutexed();
vf_procfs_rmdir(dir);
//@ close_module();
vf_printk("Helloproc module: unloaded.\n");
}