1 /****************************************************************************** 2 * 3 * Copyright (C) 2018 The Android Open Source Project 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at: 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 ***************************************************************************** 18 * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore 19 */ 20 /*! 21 ****************************************************************************** 22 * \file ihevce_dep_mngr.c 23 * 24 * \brief 25 * This file contains all the functions related to Sync manager 26 * 27 * \date 28 * 12/12/2013 29 * 30 * \author 31 * Ittiam 32 * 33 * List of Functions 34 * <TODO: TO BE ADDED> 35 * 36 ****************************************************************************** 37 */ 38 39 /*****************************************************************************/ 40 /* File Includes */ 41 /*****************************************************************************/ 42 /* System include files */ 43 #include <stdio.h> 44 #include <string.h> 45 #include <stdlib.h> 46 #include <assert.h> 47 #include <stdarg.h> 48 #include <math.h> 49 50 /* User include files */ 51 #include "ihevc_typedefs.h" 52 #include "itt_video_api.h" 53 #include "ihevc_debug.h" 54 #include "ihevc_macros.h" 55 #include "ihevc_platform_macros.h" 56 57 #include "ihevce_api.h" 58 #include "ihevce_dep_mngr_interface.h" 59 #include "ihevce_dep_mngr_private.h" 60 61 #include "cast_types.h" 62 #include "osal.h" 63 #include "osal_defaults.h" 64 65 /*****************************************************************************/ 66 /* Function Definitions */ 67 /*****************************************************************************/ 68 69 /*! 70 ****************************************************************************** 71 * \if Function name : ihevce_dmgr_get_num_mem_recs \endif 72 * 73 * \brief 74 * Number of memory records are returned for Dependency manager. 75 * 76 * \return 77 * None 78 * 79 * \author 80 * Ittiam 81 * 82 ***************************************************************************** 83 */ 84 WORD32 ihevce_dmgr_get_num_mem_recs() 85 { 86 return (NUM_DEP_MNGR_MEM_RECS); 87 } 88 89 /*! 90 ****************************************************************************** 91 * \if Function name : ihevce_dmgr_get_mem_recs \endif 92 * 93 * \brief 94 * Memory requirements are returned for Dependency manager. 95 * 96 * \param[in,out] ps_mem_tab : pointer to memory descriptors table 97 * \param[in] dep_mngr_mode : Mode of operation of dependency manager 98 * \param[in] max_num_vert_units : Maximum nunber of units to be processed 99 * \param[in] num_tile_cols : Number of column tiles for which encoder is working 100 * \param[in] num_threads : Number of threads among which sync will be established 101 * \param[in] i4_mem_space : memspace in which memory request should be done 102 * 103 * \return 104 * None 105 * 106 * \author 107 * Ittiam 108 * 109 ***************************************************************************** 110 */ 111 WORD32 ihevce_dmgr_get_mem_recs( 112 iv_mem_rec_t *ps_mem_tab, 113 WORD32 dep_mngr_mode, 114 WORD32 max_num_vert_units, 115 WORD32 num_tile_cols, 116 WORD32 num_threads, 117 WORD32 i4_mem_space) 118 { 119 WORD32 num_vert_units; 120 WORD32 num_wait_thrd_ids; 121 122 /* Dependency manager state structure */ 123 ps_mem_tab[DEP_MNGR_CTXT].i4_mem_size = sizeof(dep_mngr_state_t); 124 ps_mem_tab[DEP_MNGR_CTXT].e_mem_type = (IV_MEM_TYPE_T)i4_mem_space; 125 ps_mem_tab[DEP_MNGR_CTXT].i4_mem_alignment = 8; 126 127 /* SANITY CHECK */ 128 ASSERT( 129 (DEP_MNGR_FRM_FRM_SYNC == dep_mngr_mode) || (DEP_MNGR_ROW_FRM_SYNC == dep_mngr_mode) || 130 (DEP_MNGR_ROW_ROW_SYNC == dep_mngr_mode)); 131 132 /* Default value */ 133 if(num_tile_cols < 1) 134 { 135 num_tile_cols = 1; 136 } 137 138 /**************** Get Processed status Memory Requirements *********************/ 139 if(DEP_MNGR_FRM_FRM_SYNC == dep_mngr_mode) 140 { 141 /* for frame to frame sync 142 2 words are used for holding num units processed prev 143 2 words are used for holding num units processed curr 144 */ 145 num_vert_units = (2 + 2) * num_threads; 146 } 147 else 148 { 149 /* for both frm-row and row-row num vertical units in frame is allocated */ 150 /* (* num_tile_cols) as each column tile can separately update and check */ 151 num_vert_units = max_num_vert_units * num_tile_cols; 152 } 153 154 ps_mem_tab[DEP_MNGR_UNITS_PRCSD_MEM].i4_mem_size = (sizeof(WORD32) * num_vert_units); 155 ps_mem_tab[DEP_MNGR_UNITS_PRCSD_MEM].e_mem_type = (IV_MEM_TYPE_T)i4_mem_space; 156 ps_mem_tab[DEP_MNGR_UNITS_PRCSD_MEM].i4_mem_alignment = 8; 157 158 /**************** Get Wait thread ids Memory Requirements *********************/ 159 if(DEP_MNGR_FRM_FRM_SYNC == dep_mngr_mode) 160 { 161 /* for frame to frame sync number of threads worth memory is allocated */ 162 num_wait_thrd_ids = num_threads; 163 } 164 else if(DEP_MNGR_ROW_ROW_SYNC == dep_mngr_mode) 165 { 166 /* for row to row sync number of vertical rows worth memory is allocated */ 167 num_wait_thrd_ids = max_num_vert_units; 168 } 169 else 170 { 171 /* for row to frame sync number of threads * number of vertical rows worth memory is allocated */ 172 num_wait_thrd_ids = max_num_vert_units * num_threads; 173 } 174 175 ps_mem_tab[DEP_MNGR_WAIT_THRD_ID_MEM].i4_mem_size = (sizeof(WORD32) * num_wait_thrd_ids); 176 ps_mem_tab[DEP_MNGR_WAIT_THRD_ID_MEM].e_mem_type = (IV_MEM_TYPE_T)i4_mem_space; 177 ps_mem_tab[DEP_MNGR_WAIT_THRD_ID_MEM].i4_mem_alignment = 8; 178 179 /**************** Get Semaphore Requirements *********************/ 180 ps_mem_tab[DEP_MNGR_SEM_HANDLE_MEM].i4_mem_size = (sizeof(void *) * num_threads); 181 ps_mem_tab[DEP_MNGR_SEM_HANDLE_MEM].e_mem_type = (IV_MEM_TYPE_T)i4_mem_space; 182 ps_mem_tab[DEP_MNGR_SEM_HANDLE_MEM].i4_mem_alignment = 8; 183 184 return (NUM_DEP_MNGR_MEM_RECS); 185 } 186 187 /*! 188 ****************************************************************************** 189 * \if Function name : ihevce_dmgr_map_get_mem_recs \endif 190 * 191 * \brief 192 * Memory requirements are returned for Dependency manager. 193 * 194 * \param[in,out] ps_mem_tab : pointer to memory descriptors table 195 * \param[in] num_units : Number of units in the map 196 * \param[in] num_threads : Number of threads among which sync will be established 197 * \param[in] i4_mem_space : memspace in which memory request should be done 198 * 199 * \return 200 * None 201 * 202 * \author 203 * Ittiam 204 * 205 ***************************************************************************** 206 */ 207 WORD32 ihevce_dmgr_map_get_mem_recs( 208 iv_mem_rec_t *ps_mem_tab, WORD32 num_units, WORD32 num_threads, WORD32 i4_mem_space) 209 { 210 /* Dependency manager state structure */ 211 ps_mem_tab[DEP_MNGR_CTXT].i4_mem_size = sizeof(dep_mngr_state_t); 212 ps_mem_tab[DEP_MNGR_CTXT].e_mem_type = (IV_MEM_TYPE_T)i4_mem_space; 213 ps_mem_tab[DEP_MNGR_CTXT].i4_mem_alignment = 8; 214 215 /**************** Get Processed status Memory Requirements *********************/ 216 ps_mem_tab[DEP_MNGR_UNITS_PRCSD_MEM].i4_mem_size = (sizeof(WORD8) * num_units); 217 ps_mem_tab[DEP_MNGR_UNITS_PRCSD_MEM].e_mem_type = (IV_MEM_TYPE_T)i4_mem_space; 218 ps_mem_tab[DEP_MNGR_UNITS_PRCSD_MEM].i4_mem_alignment = 8; 219 220 /**************** Get Wait thread ids Memory Requirements *********************/ 221 /* Map-mode: semaphore post is unconditionally done on all threads */ 222 ps_mem_tab[DEP_MNGR_WAIT_THRD_ID_MEM].i4_mem_size = (sizeof(WORD32) * num_threads); 223 ps_mem_tab[DEP_MNGR_WAIT_THRD_ID_MEM].e_mem_type = (IV_MEM_TYPE_T)i4_mem_space; 224 ps_mem_tab[DEP_MNGR_WAIT_THRD_ID_MEM].i4_mem_alignment = 8; 225 226 /**************** Get Semaphore Requirements *********************/ 227 ps_mem_tab[DEP_MNGR_SEM_HANDLE_MEM].i4_mem_size = (sizeof(void *) * num_threads); 228 ps_mem_tab[DEP_MNGR_SEM_HANDLE_MEM].e_mem_type = (IV_MEM_TYPE_T)i4_mem_space; 229 ps_mem_tab[DEP_MNGR_SEM_HANDLE_MEM].i4_mem_alignment = 8; 230 231 return (NUM_DEP_MNGR_MEM_RECS); 232 } 233 234 /*! 235 ****************************************************************************** 236 * \if Function name : ihevce_dmgr_rst_frm_frm_sync \endif 237 * 238 * \brief 239 * Resets the values stored to init value 240 * 241 * \param[in,out] pv_dep_mngr_state : Pointer to Sync Manager handle. 242 * 243 * \return 244 * None 245 * 246 * \author 247 * Ittiam 248 * 249 ***************************************************************************** 250 */ 251 void ihevce_dmgr_rst_frm_frm_sync(void *pv_dep_mngr_state) 252 { 253 dep_mngr_state_t *ps_dep_mngr_state; 254 WORD32 thrds; 255 ULWORD64 *pu8_num_units_proc_prev; 256 ULWORD64 *pu8_num_units_proc_curr; 257 258 /* dep manager state structure */ 259 ps_dep_mngr_state = (dep_mngr_state_t *)pv_dep_mngr_state; 260 261 /* Reset the num units processed by each thread */ 262 pu8_num_units_proc_curr = (ULWORD64 *)ps_dep_mngr_state->pv_units_prcsd_in_row; 263 pu8_num_units_proc_prev = pu8_num_units_proc_curr + ps_dep_mngr_state->i4_num_thrds; 264 265 /* Reset the values thread ids waiting */ 266 for(thrds = 0; thrds < ps_dep_mngr_state->i4_num_thrds; thrds++) 267 { 268 pu8_num_units_proc_prev[thrds] = 0; 269 pu8_num_units_proc_curr[thrds] = 0; 270 ps_dep_mngr_state->pi4_wait_thrd_id[thrds] = -1; 271 } 272 273 return; 274 } 275 276 /*! 277 ****************************************************************************** 278 * \if Function name : ihevce_dmgr_rst_row_frm_sync \endif 279 * 280 * \brief 281 * Resets the values stored to init value 282 * 283 * \param[in,out] pv_dep_mngr_state : Pointer to Sync Manager handle. 284 * 285 * \return 286 * None 287 * 288 * \author 289 * Ittiam 290 * 291 ***************************************************************************** 292 */ 293 void ihevce_dmgr_rst_row_frm_sync(void *pv_dep_mngr_state) 294 { 295 dep_mngr_state_t *ps_dep_mngr_state; 296 WORD32 ctr, thrds; 297 298 /* dep manager state structure */ 299 ps_dep_mngr_state = (dep_mngr_state_t *)pv_dep_mngr_state; 300 301 /* Reset the values of number of units processed in a row */ 302 for(ctr = 0; ctr < ps_dep_mngr_state->i4_num_vert_units; ctr++) 303 { 304 ((WORD32 *)ps_dep_mngr_state->pv_units_prcsd_in_row)[ctr] = 0; 305 } 306 307 /* Reset the values thread ids waiting on each row */ 308 for(ctr = 0; ctr < ps_dep_mngr_state->i4_num_vert_units; ctr++) 309 { 310 for(thrds = 0; thrds < ps_dep_mngr_state->i4_num_thrds; thrds++) 311 { 312 ps_dep_mngr_state->pi4_wait_thrd_id[thrds + (ps_dep_mngr_state->i4_num_thrds * ctr)] = 313 -1; 314 } 315 } 316 317 return; 318 } 319 320 /*! 321 ****************************************************************************** 322 * \if Function name : ihevce_dmgr_map_rst_sync \endif 323 * 324 * \brief 325 * Resets the values stored to init value 326 * 327 * \param[in,out] pv_dep_mngr_state : Pointer to Sync Manager handle. 328 * 329 * \return 330 * None 331 * 332 * \author 333 * Ittiam 334 * 335 ***************************************************************************** 336 */ 337 void ihevce_dmgr_map_rst_sync(void *pv_dep_mngr_state) 338 { 339 dep_mngr_state_t *ps_dep_mngr_state; 340 WORD8 *pi1_ptr; 341 342 /* dep manager state structure */ 343 ps_dep_mngr_state = (dep_mngr_state_t *)pv_dep_mngr_state; 344 345 pi1_ptr = (WORD8 *)ps_dep_mngr_state->pv_units_prcsd_in_row - 346 ps_dep_mngr_state->ai4_tile_xtra_ctb[0] * ps_dep_mngr_state->i4_num_horz_units - 347 ps_dep_mngr_state->ai4_tile_xtra_ctb[1]; 348 349 memset( 350 pi1_ptr, 351 MAP_CTB_INIT, 352 ps_dep_mngr_state->i4_num_vert_units * ps_dep_mngr_state->i4_num_horz_units * 353 sizeof(WORD8)); 354 355 //ps_dep_mngr_state->i4_frame_map_complete = 0; 356 357 return; 358 } 359 360 /*! 361 ****************************************************************************** 362 * \if Function name : ihevce_dmgr_rst_row_row_sync \endif 363 * 364 * \brief 365 * Resets the values stored to init value 366 * 367 * \param[in,out] pv_dep_mngr_state : Pointer to Sync Manager handle. 368 * 369 * \return 370 * None 371 * 372 * \author 373 * Ittiam 374 * 375 ***************************************************************************** 376 */ 377 void ihevce_dmgr_rst_row_row_sync(void *pv_dep_mngr_state) 378 { 379 dep_mngr_state_t *ps_dep_mngr_state; 380 WORD32 ctr; 381 382 /* dep manager state structure */ 383 ps_dep_mngr_state = (dep_mngr_state_t *)pv_dep_mngr_state; 384 385 /* Reset the values of number of units processed in a row */ 386 for(ctr = 0; ctr < (ps_dep_mngr_state->i4_num_vert_units * ps_dep_mngr_state->i4_num_tile_cols); 387 ctr++) 388 { 389 ((WORD32 *)ps_dep_mngr_state->pv_units_prcsd_in_row)[ctr] = 0; 390 } 391 392 /* Reset the values thread ids waiting on each row */ 393 for(ctr = 0; ctr < ps_dep_mngr_state->i4_num_vert_units; ctr++) 394 { 395 ps_dep_mngr_state->pi4_wait_thrd_id[ctr] = -1; 396 } 397 398 return; 399 } 400 401 /*! 402 ****************************************************************************** 403 * \if Function name : ihevce_dmgr_init \endif 404 * 405 * \brief 406 * Intialization for Dependency manager state structure . 407 * 408 * \param[in] ps_mem_tab : pointer to memory descriptors table 409 * \param[in] pv_osal_handle : osal handle 410 * \param[in] dep_mngr_mode : Mode of operation of dependency manager 411 * \param[in] max_num_vert_units : Maximum nunber of units to be processed (Frame Data) 412 * \param[in] max_num_horz_units : Maximun Number of Horizontal units to be processed (Frame Data) 413 * \param[in] num_tile_cols : Number of column tiles for which encoder is working 414 * \param[in] sem_enable : Whether you want to enable semaphore or not 415 1 : Sem. Enabled, 0 : Spin lock enabled (do-while) 416 * \param[in] num_threads : Number of threads among which sync will be established 417 * \param[in] i4_mem_space : memspace in which memory request should be do 418 * 419 * \return 420 * Handle to context 421 * 422 * \author 423 * Ittiam 424 * 425 ***************************************************************************** 426 */ 427 void *ihevce_dmgr_init( 428 iv_mem_rec_t *ps_mem_tab, 429 void *pv_osal_handle, 430 WORD32 dep_mngr_mode, 431 WORD32 max_num_vert_units, 432 WORD32 max_num_horz_units, 433 WORD32 num_tile_cols, 434 WORD32 num_threads, 435 WORD32 sem_enable) 436 { 437 dep_mngr_state_t *ps_dep_mngr_state; 438 439 (void)pv_osal_handle; 440 /* dep manager state structure */ 441 ps_dep_mngr_state = (dep_mngr_state_t *)ps_mem_tab[DEP_MNGR_CTXT].pv_base; 442 443 /* dep manager memory init */ 444 ps_dep_mngr_state->ppv_thrd_sem_handles = (void **)ps_mem_tab[DEP_MNGR_SEM_HANDLE_MEM].pv_base; 445 ps_dep_mngr_state->pi4_wait_thrd_id = (WORD32 *)ps_mem_tab[DEP_MNGR_WAIT_THRD_ID_MEM].pv_base; 446 ps_dep_mngr_state->pv_units_prcsd_in_row = ps_mem_tab[DEP_MNGR_UNITS_PRCSD_MEM].pv_base; 447 448 /* SANITY CHECK */ 449 ASSERT(NULL != pv_osal_handle); 450 ASSERT( 451 (DEP_MNGR_FRM_FRM_SYNC == dep_mngr_mode) || (DEP_MNGR_ROW_FRM_SYNC == dep_mngr_mode) || 452 (DEP_MNGR_ROW_ROW_SYNC == dep_mngr_mode)); 453 454 /* Default value */ 455 if(num_tile_cols < 1) 456 { 457 num_tile_cols = 1; 458 } 459 460 /* reset the state structure variables */ 461 ps_dep_mngr_state->i4_num_horz_units = max_num_horz_units; 462 ps_dep_mngr_state->i4_num_vert_units = max_num_vert_units; 463 ps_dep_mngr_state->i1_sem_enable = sem_enable; 464 ps_dep_mngr_state->i4_dep_mngr_mode = dep_mngr_mode; 465 ps_dep_mngr_state->i4_num_thrds = num_threads; 466 ps_dep_mngr_state->i4_num_tile_cols = num_tile_cols; 467 468 /* call the reset function baed on mode */ 469 if(DEP_MNGR_FRM_FRM_SYNC == dep_mngr_mode) 470 { 471 ihevce_dmgr_rst_frm_frm_sync((void *)ps_dep_mngr_state); 472 } 473 else if(DEP_MNGR_ROW_ROW_SYNC == dep_mngr_mode) 474 { 475 ihevce_dmgr_rst_row_row_sync((void *)ps_dep_mngr_state); 476 } 477 else 478 { 479 ihevce_dmgr_rst_row_frm_sync((void *)ps_dep_mngr_state); 480 } 481 482 return ((void *)ps_dep_mngr_state); 483 } 484 485 /*! 486 ****************************************************************************** 487 * \if Function name : ihevce_dmgr_map_init \endif 488 * 489 * \brief 490 * Intialization for Dependency manager state structure . 491 * 492 * \param[in] ps_mem_tab : pointer to memory descriptors table 493 * \param[in] max_num_vert_units : Maximum nunber of units to be processed 494 * \param[in] max_num_horz_units : Maximun Number of Horizontal units to be processed 495 * \param[in] sem_enable : Whether you want to enable semaphore or not 496 1 : Sem. Enabled, 0 : Spin lock enabled (do-while) 497 * \param[in] num_threads : Number of threads among which sync will be established 498 * \param[in] ai4_tile_xtra_ctb : Array containing the number of CTBs which are 499 * are present in the Search Range outside the tile in dist-client mode. 500 * In standalone mode this array should be zero. 501 * 502 * \return 503 * Handle to context 504 * 505 * \author 506 * Ittiam 507 * 508 ***************************************************************************** 509 */ 510 void *ihevce_dmgr_map_init( 511 iv_mem_rec_t *ps_mem_tab, 512 WORD32 max_num_vert_units, 513 WORD32 max_num_horz_units, 514 WORD32 sem_enable, 515 WORD32 num_threads, 516 WORD32 ai4_tile_xtra_ctb[4]) 517 { 518 WORD32 ctr; 519 dep_mngr_state_t *ps_dep_mngr_state; 520 521 /* dep manager state structure */ 522 ps_dep_mngr_state = (dep_mngr_state_t *)ps_mem_tab[DEP_MNGR_CTXT].pv_base; 523 524 ps_dep_mngr_state->ai4_tile_xtra_ctb[0] = ai4_tile_xtra_ctb[0]; 525 ps_dep_mngr_state->ai4_tile_xtra_ctb[1] = ai4_tile_xtra_ctb[1]; 526 ps_dep_mngr_state->ai4_tile_xtra_ctb[2] = ai4_tile_xtra_ctb[2]; 527 ps_dep_mngr_state->ai4_tile_xtra_ctb[3] = ai4_tile_xtra_ctb[3]; 528 529 /* dep manager memory init */ 530 ps_dep_mngr_state->pv_units_prcsd_in_row = ps_mem_tab[DEP_MNGR_UNITS_PRCSD_MEM].pv_base; 531 ps_dep_mngr_state->pi4_wait_thrd_id = (WORD32 *)ps_mem_tab[DEP_MNGR_WAIT_THRD_ID_MEM].pv_base; 532 ps_dep_mngr_state->ppv_thrd_sem_handles = (void **)ps_mem_tab[DEP_MNGR_SEM_HANDLE_MEM].pv_base; 533 534 /* Pointing to first CTB of tile */ 535 ps_dep_mngr_state->pv_units_prcsd_in_row = 536 (void*)((WORD8*)ps_dep_mngr_state->pv_units_prcsd_in_row + 537 ps_dep_mngr_state->ai4_tile_xtra_ctb[1] + 538 max_num_horz_units * ps_dep_mngr_state->ai4_tile_xtra_ctb[0]); 539 540 /* Map-mode: semaphore post is unconditionally done on all threads. Hence 541 store these one time IDs. The use of pi4_wait_thrd_id itself can be removed 542 altogether for map-mode, but keeping it for the sake of laziness */ 543 for(ctr = 0; ctr < num_threads; ctr++) 544 { 545 ps_dep_mngr_state->pi4_wait_thrd_id[ctr] = ctr; 546 } 547 548 /* reset the state structure variables */ 549 ps_dep_mngr_state->i4_num_horz_units = max_num_horz_units; 550 ps_dep_mngr_state->i4_num_vert_units = max_num_vert_units; 551 ps_dep_mngr_state->i1_sem_enable = sem_enable; 552 ps_dep_mngr_state->i4_dep_mngr_mode = DEP_MNGR_MAP_SYNC; 553 ps_dep_mngr_state->i4_num_thrds = num_threads; 554 555 /* call the reset function baed on mode */ 556 ihevce_dmgr_map_rst_sync((void *)ps_dep_mngr_state); 557 558 return ((void *)ps_dep_mngr_state); 559 } 560 561 /*! 562 ****************************************************************************** 563 * \if Function name : ihevce_dmgr_del \endif 564 * 565 * \brief 566 * Delete the Dependency manager state structure. 567 * Note : Destroys the mutex only. System has to free the allocated memory 568 * 569 * \param[in,out] pv_dep_mngr_state : Pointer to Sync Manager handle. 570 * 571 * \return 572 * None 573 * 574 * \author 575 * Ittiam 576 * 577 ***************************************************************************** 578 */ 579 void ihevce_dmgr_del(void *pv_dep_mngr_state) 580 { 581 dep_mngr_state_t *ps_dep_mngr_state; 582 583 /* dep manager state structure */ 584 (void)ps_dep_mngr_state; 585 ps_dep_mngr_state = (dep_mngr_state_t *)pv_dep_mngr_state; 586 } 587 588 /*! 589 ****************************************************************************** 590 * \if Function name : ihevce_dmgr_register_sem_hdls \endif 591 * 592 * \brief 593 * Register sem handles of threads wihci are part of dependency group 594 * 595 * \param[in,out] pv_dep_mngr_state : Pointer to Sync Manager handle. 596 * \param[in] ppv_thread_sem_hdl : arry of pointer to all the sem handles 597 * \param[in] num_threads : Number of threads part of this dependency group 598 * 599 * \return 600 * None 601 * 602 * \author 603 * Ittiam 604 * 605 ***************************************************************************** 606 */ 607 void ihevce_dmgr_reg_sem_hdls(void *pv_dep_mngr_state, void **ppv_thread_sem_hdl, WORD32 num_threads) 608 { 609 dep_mngr_state_t *ps_dep_mngr_state; 610 WORD32 ctr; 611 612 /* dep manager state structure */ 613 ps_dep_mngr_state = (dep_mngr_state_t *)pv_dep_mngr_state; 614 615 ASSERT(num_threads <= ps_dep_mngr_state->i4_num_thrds); 616 617 for(ctr = 0; ctr < num_threads; ctr++) 618 { 619 ps_dep_mngr_state->ppv_thrd_sem_handles[ctr] = ppv_thread_sem_hdl[ctr]; 620 } 621 622 return; 623 } 624 625 /*! 626 ****************************************************************************** 627 * \if Function name : ihevce_dmgr_set_prev_done_frm_frm_sync \endif 628 * 629 * \brief 630 * Set the values to dependency not resolved state 631 * 632 * \param[in,out] pv_dep_mngr_state : Pointer to Sync Manager handle. 633 * 634 * \return 635 * None 636 * 637 * \author 638 * Ittiam 639 * 640 ***************************************************************************** 641 */ 642 void ihevce_dmgr_set_prev_done_frm_frm_sync(void *pv_dep_mngr_state) 643 { 644 dep_mngr_state_t *ps_dep_mngr_state; 645 WORD32 thrds; 646 ULWORD64 *pu8_num_units_proc_curr; 647 ULWORD64 *pu8_num_units_proc_prev; 648 649 /* dep manager state structure */ 650 ps_dep_mngr_state = (dep_mngr_state_t *)pv_dep_mngr_state; 651 652 /* Reset the values num threads entering processing state */ 653 pu8_num_units_proc_curr = (ULWORD64 *)ps_dep_mngr_state->pv_units_prcsd_in_row; 654 pu8_num_units_proc_prev = 655 (ULWORD64 *)(pu8_num_units_proc_curr + ps_dep_mngr_state->i4_num_thrds); 656 657 /* Reset the values thread ids waiting */ 658 for(thrds = 0; thrds < ps_dep_mngr_state->i4_num_thrds; thrds++) 659 { 660 pu8_num_units_proc_prev[thrds] = 1; 661 ps_dep_mngr_state->pi4_wait_thrd_id[thrds] = -1; 662 } 663 664 return; 665 } 666 667 /*! 668 ****************************************************************************** 669 * \if Function name : ihevce_dmgr_set_done_frm_frm_sync \endif 670 * 671 * \brief 672 * Set the values to dependency met state 673 * 674 * \param[in,out] pv_dep_mngr_state : Pointer to Sync Manager handle. 675 * 676 * \return 677 * None 678 * 679 * \author 680 * Ittiam 681 * 682 ***************************************************************************** 683 */ 684 void ihevce_dmgr_set_done_frm_frm_sync(void *pv_dep_mngr_state) 685 { 686 dep_mngr_state_t *ps_dep_mngr_state; 687 WORD32 thrds; 688 ULWORD64 *pu8_num_units_proc_curr; 689 690 /* dep manager state structure */ 691 ps_dep_mngr_state = (dep_mngr_state_t *)pv_dep_mngr_state; 692 693 /* Reset the values num threads entering processing state */ 694 pu8_num_units_proc_curr = (ULWORD64 *)ps_dep_mngr_state->pv_units_prcsd_in_row; 695 696 /* Reset the values thread ids waiting */ 697 for(thrds = 0; thrds < ps_dep_mngr_state->i4_num_thrds; thrds++) 698 { 699 pu8_num_units_proc_curr[thrds] = 1; 700 ps_dep_mngr_state->pi4_wait_thrd_id[thrds] = -1; 701 } 702 703 return; 704 } 705 706 /*! 707 ************************************************************************** 708 * \if Function name : ihevce_dmgr_chk_row_row_sync \endif 709 * 710 * \brief 711 * This function checks whether the dependency is met to proceed with 712 * processing. If condition is not met, it should go to a sem_wait state, 713 * else start processing. 714 * 715 * \param[in] pv_dep_mngr_state : Pointer to Sync Manager handle. 716 * \param[in] cur_offset : Current offset of the dep. variable 717 * \param[in] dep_offset : Offset from the current value to meet the dep. 718 * \param[in] dep_row : The position of the Ref. 719 * \param[in] cur_tile_col : The current column tile number (not tile id) 720 * Assuming the dependency is within the tile only (Acroos tiles won't work now) 721 * \param[in] thrd_id : Thread id of the current thread checking for dependency 722 * 723 * \return 724 * 0 on Success and -1 on error 725 * 726 * \author 727 * Ittiam 728 * 729 ************************************************************************** 730 */ 731 WORD32 ihevce_dmgr_chk_row_row_sync( 732 void *pv_dep_mngr_state, 733 WORD32 cur_offset, 734 WORD32 dep_offset, 735 WORD32 dep_row, 736 WORD32 cur_tile_col, 737 WORD32 thrd_id) 738 { 739 dep_mngr_state_t *ps_dep_mngr_state; 740 volatile WORD32 *pi4_ref_value; 741 WORD32 ref_value; 742 743 ps_dep_mngr_state = (dep_mngr_state_t *)pv_dep_mngr_state; 744 745 /* Sanity Check */ 746 ASSERT(dep_row >= 0); 747 ASSERT(dep_row < ps_dep_mngr_state->i4_num_vert_units); 748 ASSERT(cur_tile_col >= 0); 749 ASSERT(cur_tile_col < ps_dep_mngr_state->i4_num_tile_cols); 750 751 pi4_ref_value = ((volatile WORD32 *)(ps_dep_mngr_state->pv_units_prcsd_in_row)) + 752 (cur_tile_col * ps_dep_mngr_state->i4_num_vert_units) + dep_row; 753 754 /* Sanity Check */ 755 ASSERT((cur_offset + dep_offset) <= ps_dep_mngr_state->i4_num_horz_units); 756 757 /* Check whether Dep. is met */ 758 while(1) 759 { 760 ref_value = *pi4_ref_value; 761 762 if(ref_value >= (cur_offset + dep_offset)) 763 break; 764 765 if(1 == ps_dep_mngr_state->i1_sem_enable) 766 { 767 void *pv_sem_handle; 768 WORD32 ret_val; 769 770 (void)ret_val; 771 pv_sem_handle = ps_dep_mngr_state->ppv_thrd_sem_handles[thrd_id]; 772 773 /* register the thread id before going to pend state */ 774 ps_dep_mngr_state->pi4_wait_thrd_id[dep_row] = thrd_id; 775 776 /* go to the pend state */ 777 ret_val = osal_sem_wait(pv_sem_handle); 778 //ASSERT(0 == ret_val); 779 } 780 } 781 782 return 0; 783 } 784 785 /*! 786 ************************************************************************** 787 * \if Function name : ihevce_dmgr_set_row_row_sync \endif 788 * 789 * \brief 790 * This function sets the dependency and wakes up the proper semaphores 791 * to start processing. 792 * 793 * \param[in] pv_dep_mngr_state : Pointer to Sync Manager handle. 794 * \param[in] cur_offset : Current offset processed 795 * \param[in] cur_row : The cur. vertical position 796 * \param[in] cur_tile_col : The current column tile number (not tile id) 797 * Assuming the dependency is within the tile only (Acroos tiles won't work now) 798 * 799 * \return 800 * 0 on Success and -1 on error 801 * 802 * \author 803 * Ittiam 804 * 805 ************************************************************************** 806 */ 807 WORD32 ihevce_dmgr_set_row_row_sync( 808 void *pv_dep_mngr_state, WORD32 cur_offset, WORD32 cur_row, WORD32 cur_tile_col) 809 { 810 dep_mngr_state_t *ps_dep_mngr_state; 811 WORD32 *pi4_units_prcsd; 812 void *pv_sem_handle; 813 WORD32 ret_val; 814 815 (void)ret_val; 816 ps_dep_mngr_state = (dep_mngr_state_t *)pv_dep_mngr_state; 817 818 /* Sanity Check */ 819 ASSERT(cur_offset >= 0); 820 ASSERT(cur_offset <= ps_dep_mngr_state->i4_num_horz_units); 821 ASSERT(cur_row <= ps_dep_mngr_state->i4_num_vert_units); 822 ASSERT(cur_tile_col >= 0); 823 ASSERT(cur_tile_col < ps_dep_mngr_state->i4_num_tile_cols); 824 825 DATA_SYNC(); 826 827 pi4_units_prcsd = ((WORD32 *)(ps_dep_mngr_state->pv_units_prcsd_in_row)) + 828 (cur_tile_col * ps_dep_mngr_state->i4_num_vert_units) + cur_row; 829 830 /* Update the number of units processed */ 831 *pi4_units_prcsd = cur_offset; 832 833 if(1 == ps_dep_mngr_state->i1_sem_enable) 834 { 835 WORD32 wait_thrd_id; 836 837 wait_thrd_id = ps_dep_mngr_state->pi4_wait_thrd_id[cur_row]; 838 839 /* Post on threads waiting on the current row */ 840 if(-1 != wait_thrd_id) 841 { 842 pv_sem_handle = ps_dep_mngr_state->ppv_thrd_sem_handles[wait_thrd_id]; 843 /* Post on the semaphore */ 844 ret_val = osal_sem_post(pv_sem_handle); 845 //ASSERT(0 == ret_val); 846 847 ps_dep_mngr_state->pi4_wait_thrd_id[cur_row] = -1; 848 } 849 850 /* towards end of row all threads are posted (to avoid any corner cases) */ 851 if(cur_offset == ps_dep_mngr_state->i4_num_horz_units) 852 { 853 WORD32 ctr; 854 855 for(ctr = 0; ctr < ps_dep_mngr_state->i4_num_thrds; ctr++) 856 { 857 ret_val = osal_sem_post(ps_dep_mngr_state->ppv_thrd_sem_handles[ctr]); 858 //ASSERT(0 == ret_val); 859 } 860 } 861 } 862 863 return 0; 864 } 865 866 /*! 867 ************************************************************************** 868 * \if Function name : ihevce_dmgr_chk_frm_frm_sync \endif 869 * 870 * \brief 871 * This function checks whether the dependency is met to proceed with 872 * processing. If condition is not met, it should go to a sem_wait state, 873 * else start processing. 874 * For Barrier case, the thread will wait till all threads have completed 875 * the processing on the previosu instance of same stage 876 * \param[in] pv_dep_mngr_state : Pointer to Sync Manager handle. 877 * \param[in] thrd_id : Thread id checking for dependency 878 * 879 * \return 880 * 0 on Success and -1 on error 881 * 882 * \author 883 * Ittiam 884 * 885 ************************************************************************** 886 */ 887 WORD32 ihevce_dmgr_chk_frm_frm_sync(void *pv_dep_mngr_state, WORD32 thrd_id) 888 { 889 dep_mngr_state_t *ps_dep_mngr_state; 890 void *pv_sem_handle; 891 volatile ULWORD64 *pu8_num_units_proc_prev; 892 volatile ULWORD64 *pu8_num_units_proc_curr; 893 ULWORD64 prev_value; 894 ULWORD64 curr_value; 895 896 ps_dep_mngr_state = (dep_mngr_state_t *)pv_dep_mngr_state; 897 pv_sem_handle = ps_dep_mngr_state->ppv_thrd_sem_handles[thrd_id]; 898 899 pu8_num_units_proc_curr = (volatile ULWORD64 *)ps_dep_mngr_state->pv_units_prcsd_in_row; 900 pu8_num_units_proc_prev = 901 (volatile ULWORD64 *)(pu8_num_units_proc_curr + ps_dep_mngr_state->i4_num_thrds); 902 903 /* Check whether Dep. is met */ 904 while(1) 905 { 906 WORD32 ret_val; 907 908 (void)ret_val; 909 curr_value = pu8_num_units_proc_curr[thrd_id]; 910 prev_value = pu8_num_units_proc_prev[thrd_id]; 911 912 if(curr_value == (prev_value + 1)) 913 { 914 break; 915 } 916 else 917 { 918 /* register the thread id before going to pend state */ 919 ps_dep_mngr_state->pi4_wait_thrd_id[thrd_id] = thrd_id; 920 921 /* go to the pend state */ 922 ret_val = osal_sem_wait(pv_sem_handle); 923 //ASSERT(0 == ret_val); 924 } 925 } 926 927 /* store curr value to prev for next iteration */ 928 pu8_num_units_proc_prev[thrd_id] = pu8_num_units_proc_curr[thrd_id]; 929 930 return 0; 931 } 932 933 /*! 934 ************************************************************************** 935 * \if Function name : ihevce_dmgr_update_frm_frm_sync \endif 936 * 937 * \brief 938 * This function sets the dependency and wakes up the proper semaphores 939 * to start processing. 940 * For barrier case, if the dep. is met, all waiting threads should be waked up 941 * 942 * \param[in] pv_dep_mngr_state : Pointer to Sync Manager handle. 943 * 944 * \return 945 * 0 on Success and -1 on error 946 * 947 * \author 948 * Ittiam 949 * 950 ************************************************************************** 951 */ 952 WORD32 ihevce_dmgr_update_frm_frm_sync(void *pv_dep_mngr_state) 953 { 954 dep_mngr_state_t *ps_dep_mngr_state; 955 void *pv_sem_handle; 956 volatile ULWORD64 *pu8_num_units_proc_curr; 957 WORD32 ctr; 958 959 ps_dep_mngr_state = (dep_mngr_state_t *)pv_dep_mngr_state; 960 961 pu8_num_units_proc_curr = (volatile ULWORD64 *)ps_dep_mngr_state->pv_units_prcsd_in_row; 962 963 /* Post on All vertical waiting threads semaphores & update the cur unit proc */ 964 for(ctr = 0; ctr < ps_dep_mngr_state->i4_num_thrds; ctr++) 965 { 966 WORD32 ret_val; 967 WORD32 wait_thrd_id; 968 969 (void)ret_val; 970 /* increment the curr unit counter for all threads */ 971 pu8_num_units_proc_curr[ctr] = pu8_num_units_proc_curr[ctr] + 1; 972 973 wait_thrd_id = ctr; 974 //wait_thrd_id = ps_dep_mngr_state->pi4_wait_thrd_id[ctr]; 975 976 if(-1 != wait_thrd_id) 977 { 978 pv_sem_handle = ps_dep_mngr_state->ppv_thrd_sem_handles[wait_thrd_id]; 979 /* Post on the semaphore */ 980 ret_val = osal_sem_post(pv_sem_handle); 981 //ASSERT(0 == ret_val); 982 983 ps_dep_mngr_state->pi4_wait_thrd_id[ctr] = -1; 984 } 985 } 986 987 return 0; 988 } 989 990 /*! 991 ************************************************************************** 992 * \if Function name : ihevce_dmgr_map_chk \endif 993 * 994 * \brief 995 * This function checks whether all entries in the dependency map are set 996 * 997 * \param[in] pu1_start : Pointer to the start of the search area 998 * \param[in] i4_num_ctb_x : Size of search area 999 * \param[in] i4_num_ctb_y : Size of search area 1000 * \param[in] i4_stride : Stride of search area 1001 * 1002 * \return 1003 * 1 on Success otherwise 0 1004 * 1005 * \author 1006 * Ittiam 1007 * 1008 ************************************************************************** 1009 */ 1010 WORD32 1011 ihevce_dmgr_map_chk(WORD8 *pu1_start, WORD32 i4_num_ctb_x, WORD32 i4_num_ctb_y, WORD32 i4_stride) 1012 { 1013 WORD8 *pi1_ctb = pu1_start; 1014 WORD32 row, col; 1015 WORD32 map_ready_flag = MAP_CTB_COMPLETE; 1016 1017 for(row = 0; row < i4_num_ctb_y; row++) 1018 { 1019 for(col = 0; col < i4_num_ctb_x; col++) 1020 { 1021 map_ready_flag &= pi1_ctb[col]; 1022 } 1023 pi1_ctb += i4_stride; 1024 } 1025 1026 /* NOTE: early exit in the above loop can taken if map_ready_flag 1027 is found to be zero somewhere at the start itself */ 1028 return (map_ready_flag == MAP_CTB_COMPLETE); 1029 } 1030 1031 /*! 1032 ************************************************************************** 1033 * \if Function name : ihevce_dmgr_map_chk_sync \endif 1034 * 1035 * \brief 1036 * This function checks whether the dependency is met by searching in a 1037 * rectangular area. If condition is not met, it should go to a sem_wait state, 1038 * else start processing. 1039 * 1040 * \param[in] pv_dep_mngr_state : Pointer to Sync Manager handle. 1041 * \param[in] thrd_id : Thread id of the current thread checking for dependency 1042 * \param[in] offset_x : Offset of current CTB in Tile in ctb-unit 1043 * \param[in] offset_y : Offset of current CTB in Tile in ctb-unit 1044 * \param[in] i4_sr_ctb_x : Search Range in ctb-unit 1045 * \param[in] i4_sr_ctb_y : Search Range in ctb-unit 1046 * 1047 * \return 1048 * 0 on Success and -1 on error 1049 * 1050 * \author 1051 * Ittiam 1052 * 1053 ************************************************************************** 1054 */ 1055 WORD32 ihevce_dmgr_map_chk_sync( 1056 void *pv_dep_mngr_state, 1057 WORD32 thrd_id, 1058 WORD32 offset_x, 1059 WORD32 offset_y, 1060 WORD32 i4_sr_ctb_x, 1061 WORD32 i4_sr_ctb_y) 1062 { 1063 dep_mngr_state_t *ps_dep_mngr_state; 1064 volatile WORD8 *pi1_ctb; 1065 WORD8 *pi1_tile_start; 1066 WORD32 i4_avail_left, i4_avail_right, i4_avail_top, i4_avail_bot; 1067 WORD32 i4_num_ctb_x, i4_num_ctb_y; 1068 WORD32 i4_stride; 1069 WORD32 i4_tile_wd, i4_tile_ht; //in ctb units 1070 1071 ps_dep_mngr_state = (dep_mngr_state_t *)pv_dep_mngr_state; 1072 1073 i4_tile_wd = ps_dep_mngr_state->i4_num_horz_units - ps_dep_mngr_state->ai4_tile_xtra_ctb[1] - 1074 ps_dep_mngr_state->ai4_tile_xtra_ctb[2]; 1075 1076 i4_tile_ht = ps_dep_mngr_state->i4_num_vert_units - ps_dep_mngr_state->ai4_tile_xtra_ctb[0] - 1077 ps_dep_mngr_state->ai4_tile_xtra_ctb[3]; 1078 1079 i4_stride = ps_dep_mngr_state->i4_num_horz_units; 1080 1081 /* Sanity Checks, confirm if ctb offsets are within tiles */ 1082 ASSERT(offset_x >= 0); 1083 ASSERT(offset_y >= 0); 1084 ASSERT(offset_x < i4_tile_wd); 1085 ASSERT(offset_y < i4_tile_ht); 1086 1087 pi1_tile_start = (WORD8 *)ps_dep_mngr_state->pv_units_prcsd_in_row; 1088 pi1_ctb = (volatile WORD8 *)pi1_tile_start; 1089 1090 if(ps_dep_mngr_state->ai4_tile_xtra_ctb[0]) 1091 { 1092 i4_avail_top = i4_sr_ctb_y; 1093 } 1094 else 1095 { 1096 i4_avail_top = MIN(i4_sr_ctb_y, offset_y); 1097 } 1098 1099 if(ps_dep_mngr_state->ai4_tile_xtra_ctb[1]) 1100 { 1101 i4_avail_left = i4_sr_ctb_x; 1102 } 1103 else 1104 { 1105 i4_avail_left = MIN(i4_sr_ctb_x, offset_x); 1106 } 1107 1108 if(ps_dep_mngr_state->ai4_tile_xtra_ctb[2]) 1109 { 1110 i4_avail_right = i4_sr_ctb_x; 1111 } 1112 else 1113 { 1114 i4_avail_right = MIN(i4_sr_ctb_x, (i4_tile_wd - offset_x - 1)); 1115 } 1116 1117 if(ps_dep_mngr_state->ai4_tile_xtra_ctb[3]) 1118 { 1119 i4_avail_bot = i4_sr_ctb_y; 1120 } 1121 else 1122 { 1123 i4_avail_bot = MIN(i4_sr_ctb_y, (i4_tile_ht - offset_y - 1)); 1124 } 1125 1126 i4_num_ctb_x = (i4_avail_left + 1 + i4_avail_right); 1127 i4_num_ctb_y = (i4_avail_top + 1 + i4_avail_bot); 1128 1129 /* Point to the start of the search-area */ 1130 pi1_ctb += ((offset_y - i4_avail_top) * i4_stride + (offset_x - i4_avail_left)); 1131 1132 /* Check whether Dep. is met */ 1133 while(1) 1134 { 1135 if(1 == ihevce_dmgr_map_chk((WORD8 *)pi1_ctb, i4_num_ctb_x, i4_num_ctb_y, i4_stride)) 1136 { 1137 break; 1138 } 1139 else 1140 { 1141 if(1 == ps_dep_mngr_state->i1_sem_enable) 1142 { 1143 osal_sem_wait(ps_dep_mngr_state->ppv_thrd_sem_handles[thrd_id]); 1144 } 1145 } 1146 } 1147 1148 return 0; 1149 } 1150 1151 /*! 1152 ************************************************************************** 1153 * \if Function name : ihevce_dmgr_map_set_sync \endif 1154 * 1155 * \brief 1156 * This function sets the dependency and wakes up the proper semaphores 1157 * to start processing. 1158 * 1159 * \param[in] pv_dep_mngr_state : Pointer to Sync Manager handle. 1160 * \param[in] offset_x : Offset of current CTB in Tile(ctb unit) 1161 * \param[in] offset_y : Offset of current CTB in Tile(ctb unit) 1162 * 1163 * \return 1164 * 0 on Success and -1 on error 1165 * 1166 * \author 1167 * Ittiam 1168 * 1169 ************************************************************************** 1170 */ 1171 WORD32 ihevce_dmgr_map_set_sync( 1172 void *pv_dep_mngr_state, WORD32 offset_x, WORD32 offset_y, WORD32 i4_map_value) 1173 { 1174 dep_mngr_state_t *ps_dep_mngr_state; 1175 WORD8 *pi1_tile_start; 1176 WORD32 map_stride; 1177 1178 ps_dep_mngr_state = (dep_mngr_state_t *)pv_dep_mngr_state; 1179 1180 /* Sanity Checks */ 1181 ASSERT(offset_x >= (-ps_dep_mngr_state->ai4_tile_xtra_ctb[1])); 1182 ASSERT(offset_y >= (-ps_dep_mngr_state->ai4_tile_xtra_ctb[0])); 1183 1184 ASSERT( 1185 offset_x < 1186 (ps_dep_mngr_state->i4_num_horz_units - ps_dep_mngr_state->ai4_tile_xtra_ctb[1])); 1187 1188 ASSERT( 1189 offset_y < 1190 (ps_dep_mngr_state->i4_num_vert_units - ps_dep_mngr_state->ai4_tile_xtra_ctb[0])); 1191 1192 DATA_SYNC(); 1193 1194 map_stride = ps_dep_mngr_state->i4_num_horz_units; 1195 1196 pi1_tile_start = (WORD8 *)ps_dep_mngr_state->pv_units_prcsd_in_row; 1197 1198 /* Set the flag to indicate that this CTB has been processed */ 1199 *(pi1_tile_start + offset_y * map_stride + offset_x) = (WORD8)i4_map_value; 1200 1201 if(1 == ps_dep_mngr_state->i1_sem_enable) 1202 { 1203 WORD32 wait_thrd_id; 1204 1205 /* Post on threads waiting on the current row */ 1206 for(wait_thrd_id = 0; wait_thrd_id < ps_dep_mngr_state->i4_num_thrds; wait_thrd_id++) 1207 { 1208 /* Post on the semaphore */ 1209 /* Map-mode: semaphore post is unconditionally done on all threads */ 1210 osal_sem_post(ps_dep_mngr_state->ppv_thrd_sem_handles[wait_thrd_id]); 1211 } 1212 } 1213 1214 return 0; 1215 } 1216