3 * sushivision copyright (C) 2006-2007 Monty <monty@xiph.org>
5 * sushivision is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * sushivision is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with sushivision; see the file COPYING. If not, write to the
17 * Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
30 #include <sys/types.h>
38 static pthread_mutex_t m
= PTHREAD_MUTEX_INITIALIZER
;
39 static pthread_cond_t mc
= PTHREAD_COND_INITIALIZER
;
40 sig_atomic_t _sushiv_exiting
=0;
41 static int wake_pending
= 0;
42 static int num_threads
;
44 static int instances
=0;
45 static sushiv_instance_t
**instance_list
;
47 void _sushiv_clean_exit(int sig
){
49 _sushiv_wake_workers();
51 //signal(sig,SIG_IGN);
54 "\nTrapped signal %d; exiting!\n",sig
);
59 static int num_proccies(){
60 FILE *f
= fopen("/proc/cpuinfo","r");
66 if (f
== NULL
) return 1;
67 while ((read
= getline(&line
, &len
, f
)) != -1) {
68 if(sscanf(line
,"processor : %d",&arg
)==1)
69 if(arg
+1>num
)num
=arg
+1;
74 fprintf(stderr
,"Number of processors: %d\n",num
);
79 void _sushiv_wake_workers(){
81 pthread_mutex_lock(&m
);
82 wake_pending
= num_threads
;
83 pthread_cond_broadcast(&mc
);
84 pthread_mutex_unlock(&m
);
88 void _maintain_cache(sushiv_panel_t
*p
, _sushiv_compute_cache
*c
, int w
){
90 /* toplevel initialization */
94 /* determine which functions are actually needed */
95 c
->call
= calloc(p
->sushi
->functions
,sizeof(*c
->call
));
96 c
->fout
= calloc(p
->sushi
->functions
,sizeof(*c
->fout
));
97 for(i
=0;i
<p
->objectives
;i
++){
98 sushiv_objective_t
*o
= p
->objective_list
[i
].o
;
99 for(j
=0;j
<o
->outputs
;j
++)
100 c
->call
[o
->function_map
[j
]]=
101 p
->sushi
->function_list
[o
->function_map
[j
]]->callback
;
105 /* once to begin, as well as anytime the data width changes */
106 if(c
->storage_width
< w
){
108 c
->storage_width
= w
;
110 for(i
=0;i
<p
->sushi
->functions
;i
++){
112 if(c
->fout
[i
])free(c
->fout
[i
]);
113 c
->fout
[i
] = malloc(w
* p
->sushi
->function_list
[i
]->outputs
*
120 static void *worker_thread(void *dummy
){
121 /* set up temporary working space for function rendering; this saves
122 continuously recreating it in the loop below */
123 _sushiv_compute_cache
**c
; // [instance][panel]
126 c
= calloc(instances
,sizeof(*c
));
127 for(j
=0;j
<instances
;j
++){
128 sushiv_instance_t
*s
= instance_list
[j
];
129 c
[j
] = calloc(s
->panels
,sizeof(**c
));
133 if(_sushiv_exiting
)break;
139 for(j
=0;j
<instances
;j
++){
140 sushiv_instance_t
*s
= instance_list
[j
];
142 for(i
=0;i
<s
->panels
;i
++){
143 sushiv_panel_t
*p
= s
->panel_list
[i
];
145 if(_sushiv_exiting
)break;
147 // pending remap work?
149 if(p
->private->maps_dirty
&& !p
->private->maps_rendering
){
150 p
->private->maps_dirty
= 0;
151 p
->private->maps_rendering
= 1;
154 gdk_threads_leave ();
155 p
->private->map_redraw(p
);
156 gdk_threads_enter ();
158 p
->private->maps_rendering
= 0;
161 // pending legend work?
162 if(p
->private->legend_dirty
&& !p
->private->legend_rendering
){
163 p
->private->legend_dirty
= 0;
164 p
->private->legend_rendering
= 1;
167 gdk_threads_leave ();
168 p
->private->legend_redraw(p
);
169 gdk_threads_enter ();
171 p
->private->legend_rendering
= 0;
173 gdk_threads_leave ();
175 // pending computation work?
176 flag
|= _sushiv_panel_cooperative_compute(s
->panel_list
[i
],
183 // nothing to do, wait
184 pthread_mutex_lock(&m
);
186 pthread_cond_wait(&mc
,&m
);
189 pthread_mutex_unlock(&m
);
192 pthread_mutex_unlock(&m
);
196 static char * gtkrc_string(){
201 static void sushiv_realize_instance(sushiv_instance_t
*s
){
203 for(i
=0;i
<s
->panels
;i
++)
204 _sushiv_realize_panel(s
->panel_list
[i
]);
205 for(i
=0;i
<s
->panels
;i
++)
206 s
->panel_list
[i
]->private->request_compute(s
->panel_list
[i
]);
209 static void sushiv_realize_all(void){
211 for(i
=0;i
<instances
;i
++)
212 sushiv_realize_instance(instance_list
[i
]);
215 /* externally visible interface */
217 sushiv_instance_t
*sushiv_new_instance(void) {
218 sushiv_instance_t
*ret
=calloc(1,sizeof(*ret
));
219 ret
->private = calloc(1,sizeof(*ret
->private));
222 instance_list
= realloc(instance_list
,(instances
+1)*sizeof(*instance_list
));
224 instance_list
= malloc((instances
+1)*sizeof(*instance_list
));
226 instance_list
[instances
] = ret
;
232 int main (int argc
, char *argv
[]){
235 num_threads
= num_proccies();
237 gtk_init (&argc
, &argv
);
238 g_thread_init (NULL
);
242 gtk_rc_parse_string(gtkrc_string());
243 gtk_rc_add_default_file("sushi-gtkrc");
245 ret
= sushiv_submain(argc
,argv
);
248 sushiv_realize_all();
252 int threads
= num_threads
;
254 pthread_create(&dummy
, NULL
, &worker_thread
,NULL
);
257 signal(SIGINT
,_sushiv_clean_exit
);
258 //signal(SIGSEGV,_sushiv_clean_exit);
264 int (*optional_exit
)(void) = dlsym(RTLD_DEFAULT
, "sushiv_atexit");
266 return optional_exit();