From patchwork Mon Mar 1 21:39:40 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pauli Nieminen X-Patchwork-Id: 83071 Received: from lists.sourceforge.net (lists.sourceforge.net [216.34.181.88]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o21LfLEd005300 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Mon, 1 Mar 2010 21:41:58 GMT Received: from localhost ([127.0.0.1] helo=sfs-ml-2.v29.ch3.sourceforge.com) by sfs-ml-2.v29.ch3.sourceforge.com with esmtp (Exim 4.69) (envelope-from ) id 1NmDLa-0007dZ-J8; Mon, 01 Mar 2010 21:40:14 +0000 Received: from sfi-mx-4.v28.ch3.sourceforge.com ([172.29.28.124] helo=mx.sourceforge.net) by sfs-ml-2.v29.ch3.sourceforge.com with esmtp (Exim 4.69) (envelope-from ) id 1NmDLY-0007dS-Uy for dri-devel@lists.sourceforge.net; Mon, 01 Mar 2010 21:40:12 +0000 Received-SPF: neutral (sfi-mx-4.v28.ch3.sourceforge.com: 213.243.153.184 is neither permitted nor denied by domain of gmail.com) client-ip=213.243.153.184; envelope-from=suokkos@gmail.com; helo=filtteri1.pp.htv.fi; Received: from filtteri1.pp.htv.fi ([213.243.153.184]) by sfi-mx-4.v28.ch3.sourceforge.com with esmtp (Exim 4.69) id 1NmDLX-0003EX-Dj for dri-devel@lists.sourceforge.net; Mon, 01 Mar 2010 21:40:12 +0000 Received: from localhost (localhost [127.0.0.1]) by filtteri1.pp.htv.fi (Postfix) with ESMTP id 0B5A48BBB9; Mon, 1 Mar 2010 23:40:03 +0200 (EET) X-Virus-Scanned: Debian amavisd-new at pp.htv.fi Received: from smtp6.welho.com ([213.243.153.40]) by localhost (filtteri1.pp.htv.fi [213.243.153.184]) (amavisd-new, port 10024) with ESMTP id bA0CphAAVYDt; Mon, 1 Mar 2010 23:40:02 +0200 (EET) Received: from localhost.localdomain (cs181130083.pp.htv.fi [82.181.130.83]) by smtp6.welho.com (Postfix) with ESMTP id 8C50A5BC003; Mon, 1 Mar 2010 23:40:02 +0200 (EET) From: Pauli Nieminen To: dri-devel@lists.sourceforge.net Subject: [PATCH] libdrm_radeon: Optimize reloc writing to do less looping. Date: Mon, 1 Mar 2010 23:39:40 +0200 Message-Id: <1267479580-14735-1-git-send-email-suokkos@gmail.com> X-Mailer: git-send-email 1.6.3.3 X-Spam-Score: 1.2 (+) X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. 1.2 SPF_NEUTRAL SPF: sender does not match SPF record (neutral) X-Headers-End: 1NmDLX-0003EX-Dj X-BeenThere: dri-devel@lists.sourceforge.net X-Mailman-Version: 2.1.9 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.sourceforge.net X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Mon, 01 Mar 2010 21:41:58 +0000 (UTC) diff --git a/radeon/radeon_bo_gem.c b/radeon/radeon_bo_gem.c index bc8058d..1b33bdb 100644 --- a/radeon/radeon_bo_gem.c +++ b/radeon/radeon_bo_gem.c @@ -80,6 +80,7 @@ static struct radeon_bo *bo_open(struct radeon_bo_manager *bom, bo->base.domains = domains; bo->base.flags = flags; bo->base.ptr = NULL; + bo->base.referenced_in_cs = 0; bo->map_count = 0; if (handle) { struct drm_gem_open open_arg; diff --git a/radeon/radeon_bo_int.h b/radeon/radeon_bo_int.h index 9589ead..d1df829 100644 --- a/radeon/radeon_bo_int.h +++ b/radeon/radeon_bo_int.h @@ -17,7 +17,7 @@ struct radeon_bo_int { unsigned cref; struct radeon_bo_manager *bom; uint32_t space_accounted; - uint32_t referenced_in_cs; + unsigned long referenced_in_cs; }; /* bo functions */ diff --git a/radeon/radeon_cs_gem.c b/radeon/radeon_cs_gem.c index 45a219c..d23aa35 100644 --- a/radeon/radeon_cs_gem.c +++ b/radeon/radeon_cs_gem.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include "radeon_cs.h" @@ -63,11 +64,49 @@ struct cs_gem { struct radeon_cs_int base; struct drm_radeon_cs cs; struct drm_radeon_cs_chunk chunks[2]; + unsigned long id; unsigned nrelocs; uint32_t *relocs; struct radeon_bo_int **relocs_bo; }; +static pthread_mutex_t id_mutex = PTHREAD_MUTEX_INITIALIZER; +static unsigned long cs_id_source = 0; + +/** + * Returns a free id for cs. + * If there is no free id we return zero + **/ +static unsigned long generate_id(void) +{ + unsigned long r = 0,x; + pthread_mutex_lock( &id_mutex ); + /* check for free ids */ + if (cs_id_source != ~r) { + /* find first zero bit */ + x = cs_id_source + 1; /* 10111 -> 1100 */ + r = ~cs_id_source; /* 10111 -> 0100 */ + r = x & r; /* x & r -> 0100 */ + + /* set id as reserved */ + cs_id_source |= r; + } + pthread_mutex_unlock( &id_mutex ); + return r; +} + +/** + * Free the id for later reuse + **/ +static void free_id(unsigned long id) +{ + pthread_mutex_lock( &id_mutex ); + + cs_id_source &= ~id; + + pthread_mutex_unlock( &id_mutex ); +} + static struct radeon_cs_int *cs_gem_create(struct radeon_cs_manager *csm, uint32_t ndw) { @@ -90,6 +129,7 @@ static struct radeon_cs_int *cs_gem_create(struct radeon_cs_manager *csm, } csg->base.relocs_total_size = 0; csg->base.crelocs = 0; + csg->id = generate_id(); csg->nrelocs = 4096 / (4 * 4) ; csg->relocs_bo = (struct radeon_bo_int**)calloc(1, csg->nrelocs*sizeof(void*)); @@ -141,38 +181,43 @@ static int cs_gem_write_reloc(struct radeon_cs_int *cs, if (write_domain == RADEON_GEM_DOMAIN_CPU) { return -EINVAL; } - /* check if bo is already referenced */ - for(i = 0; i < cs->crelocs; i++) { - idx = i * RELOC_SIZE; - reloc = (struct cs_reloc_gem*)&csg->relocs[idx]; - if (reloc->handle == bo->handle) { - /* Check domains must be in read or write. As we check already - * checked that in argument one of the read or write domain was - * set we only need to check that if previous reloc as the read - * domain set then the read_domain should also be set for this - * new relocation. - */ - /* the DDX expects to read and write from same pixmap */ - if (write_domain && (reloc->read_domain & write_domain)) { - reloc->read_domain = 0; - reloc->write_domain = write_domain; - } else if (read_domain & reloc->write_domain) { - reloc->read_domain = 0; - } else { - if (write_domain != reloc->write_domain) - return -EINVAL; - if (read_domain != reloc->read_domain) - return -EINVAL; + /* use bit field hash functionto determine + if this bo is for sure not in this cs.*/ + if ((boi->referenced_in_cs & csg->id)) { + /* check if bo is already referenced */ + for(i = cs->crelocs; i != 0;) { + --i; + idx = i * RELOC_SIZE; + reloc = (struct cs_reloc_gem*)&csg->relocs[idx]; + if (reloc->handle == bo->handle) { + /* Check domains must be in read or write. As we check already + * checked that in argument one of the read or write domain was + * set we only need to check that if previous reloc as the read + * domain set then the read_domain should also be set for this + * new relocation. + */ + /* the DDX expects to read and write from same pixmap */ + if (write_domain && (reloc->read_domain & write_domain)) { + reloc->read_domain = 0; + reloc->write_domain = write_domain; + } else if (read_domain & reloc->write_domain) { + reloc->read_domain = 0; + } else { + if (write_domain != reloc->write_domain) + return -EINVAL; + if (read_domain != reloc->read_domain) + return -EINVAL; + } + + reloc->read_domain |= read_domain; + reloc->write_domain |= write_domain; + /* update flags */ + reloc->flags |= (flags & reloc->flags); + /* write relocation packet */ + radeon_cs_write_dword((struct radeon_cs *)cs, 0xc0001000); + radeon_cs_write_dword((struct radeon_cs *)cs, idx); + return 0; } - - reloc->read_domain |= read_domain; - reloc->write_domain |= write_domain; - /* update flags */ - reloc->flags |= (flags & reloc->flags); - /* write relocation packet */ - radeon_cs_write_dword((struct radeon_cs *)cs, 0xc0001000); - radeon_cs_write_dword((struct radeon_cs *)cs, idx); - return 0; } } /* new relocation */ @@ -203,6 +248,7 @@ static int cs_gem_write_reloc(struct radeon_cs_int *cs, reloc->flags = flags; csg->chunks[1].length_dw += RELOC_SIZE; radeon_bo_ref(bo); + boi->referenced_in_cs |= csg->id; cs->relocs_total_size += boi->size; radeon_cs_write_dword((struct radeon_cs *)cs, 0xc0001000); radeon_cs_write_dword((struct radeon_cs *)cs, idx); @@ -288,6 +334,7 @@ static int cs_gem_emit(struct radeon_cs_int *cs) &csg->cs, sizeof(struct drm_radeon_cs)); for (i = 0; i < csg->base.crelocs; i++) { csg->relocs_bo[i]->space_accounted = 0; + csg->relocs_bo[i]->referenced_in_cs &= ~csg->id; radeon_bo_unref((struct radeon_bo *)csg->relocs_bo[i]); csg->relocs_bo[i] = NULL; } @@ -302,6 +349,7 @@ static int cs_gem_destroy(struct radeon_cs_int *cs) { struct cs_gem *csg = (struct cs_gem*)cs; + free_id(csg->id); free(csg->relocs_bo); free(cs->relocs); free(cs->packets); @@ -317,6 +365,7 @@ static int cs_gem_erase(struct radeon_cs_int *cs) if (csg->relocs_bo) { for (i = 0; i < csg->base.crelocs; i++) { if (csg->relocs_bo[i]) { + csg->relocs_bo[i]->referenced_in_cs &= ~csg->id; radeon_bo_unref((struct radeon_bo *)csg->relocs_bo[i]); csg->relocs_bo[i] = NULL; }